I'm an absolute beginner on EF, and I am stuck at what probably is very simple.
I have 2 tables/classes:
Toys and Brands
public class Toys
{
public int Id { get; set; }
public string Name { get; set; }
public int BrandId { get; set; }
}
public class Brands
{
public int BrandId { get; set; }
public string BrandName { get; set; }
}
My DBContext file:
public class SOT : DbContext
{ public SOT(): base("name=SOT")
{
public virtual DbSet<Brands> brands; set; }
public virtual DbSet<Toys> toys { get; set; }
}
When I add a record, the BrandId goes to the BrandId field in the Toys table.
I want to display in the view the Name of the toy, and the Brand Name. Now I get toy name and Brand Id
In my controller, on the Index Action:
public ViewResult Index()
{
/// this is where I am sooo stuck.....
var toy = _context.Toys.Include(c => c.Brands).ToList();
return View(toy);
}
The view:
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.BrandName)
</td>
What am I doing wrong?
maybe this will helps you, If you make a relation between Toy and Brand Table
var q = _context.Toys
.Select(q_toys =>
new
{
q_toys.Name,
q_toys.Brand.BrandName
}).ToList();
Related
I'm using Visual Studio 2015, .Net framework 4.6.00079 to build a simple ASP.NET MVC 6 app:
model:
namespace RimconPensionModel.DataAccessLayer
{
[Table("BaseMortality")]
public class BaseMortality
{
[Key]
public int Id { get; set; }
public string BaseMortalitySet { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public float MortalityFactor { get; set; }
public DateTime EffectiveDate { get; set; }
public DateTime UpdateDate { get; set; }
public string UpdateUser { get; set; }
}
}
controller:
namespace RimconPensionModel.Controllers
{
public class BaseMortalityController : Controller
{
[FromServices]
public RimconPensionModelContext RimconPensionModelContext { get; set; }
[FromServices]
public ILogger<BaseMortalityController> Logger { get; set; }
public IActionResult Index()
{
return View(RimconPensionModelContext.BaseMortality.ToList());
}
}
}
view:
#model IEnumerable<RimconPensionModel.DataAccessLayer.BaseMortality>
#{
ViewBag.Title = "Base Mortality Data";
}
<h2>Base Mortality Data</h2>
<!--
<p>
<a asp-controller="BaseMortalityData" asp-action="Create">Create New</a>
</p> -->
<table class="table">
<tr>
<th>Base Mortality Sets</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.BaseMortalitySet)
</td>
</tr>
}
</table>
The app builds and starts, but when I invoke the controller, I get InvalidCastException on the "return View( . . . )" line of the controller. I've been googling for days (I'm a bit new to MVC and Entity Framework) with no luck. I think it probably has something to do with the datetime attributes. I bulk loaded the database table from a csv file with the datetime fields in YYYYMMDD format and the load went OK; the db table shows 1994-12-31 12:00:00 AM in the datetime fields. They are type datetime2(7), NOT NULL in the db.
I have a table that references itself, but I am struggling with getting my desired mapping. I want to be able to define Children to be a collection of people that have a given person as Mother, Father, and/or Guardian. A Guardian may be the father or mother.
I am wanting to have a tree view of people that is browsable where people are listed; the user can expand a person's node to show all that person's children, regardless off the child-defining relationship (Mother, Father, or Guardian).
public partial class Person
{
[Key]
public int ID { get; set; }
[StringLength(100)]
public string Name { get; set; }
public int? GuardianID { get; set; }
[Column("MotherID")]
public int? MotherID { get; set; }
[Column("FatherID")]
public int? FatherID { get; set; }
[ForeignKey("MotherID")]
public virtual tblPerson Mother { get; set; }
[ForeignKey("FatherID")]
public virtual tblPerson Father { get; set; }
[ForeignKey("GuardianID")]
public virtual tblPerson Guardian { get; set; }
[InverseProperty("Guardian")]
[InverseProperty("Father")]
[InverseProperty("Mother")]
public virtual IEnumerable<tblPerson> children { get; set; }
}
Any help would be appreciated right now my view has to look like this:
#using Person_MVC.Models
#model IEnumerable<Person>
#{
IEnumerable<Person> children;
}
<ul>
#foreach (Person person in Model.OrderBy(p => p.PersonNumber))
{
<li id="Pnl_#Person.ID" data-jstree='{"type":"Person"}' data-Personkey="#Person.ID.ToString()">
#Person.Name
#{
PersonModel db = new PersonModel();
children = (from p in db.Persons where p.GuardianID == Person.ID || p.Father == Person.ID || p.MotherID == Person.ID select p).ToList();
}
#if (children != null && children.Count() > 0)
{
#Html.Partial("PersonTree", children)
}
</li>
}
</ul>
I guess the better solution is to make three navigation lists in your model and may have one method to join the objects to return all sons to you.
e.g.
public int? FatherId { get; set; }
public int? GrandFatherId { get; set; }
public int? MotherId { get; set; }
public virtual ICollection<Person> FatherForThose { get; set; }
public virtual Person Father { get; set; }
public virtual ICollection<Person> GrandFatherForThose { get; set; }
public virtual Person GrandFather { get; set; }
public virtual ICollection<Person> MotherForThose { get; set; }
public virtual Person Mother { get; set; }
public ICollection<Person> GetChildren()
{
var list = FatherForThose.Concat(MotherForThose).ToList();
foreach (var person in GrandFatherForThose)
{
if (list.All(i => i.Id != person.Id))
{
list.Add(person);
}
}
return list;
}
but you should always take care to include them in your querying
e.g.
var grand = context.Persons.Include(x => x.FatherForThose)
.Include(x => x.GrandFatherForThose)
.Include(x => x.MotherForThose)
.FirstOrDefault(x => x.Id == 2);
var list = grand.GetChildren();
All the table data should be in hand (If not we might have multiple calls to database).
Find list of all the Persons who doesn't have parents(i.e; no guardianid, motherid, parentid for a person) and start the partial with them.
Try can this too...
public partial class Person
{
[Key]
public int ID { get; set; }
[StringLength(100)]
public string Name { get; set; }
public int? GuardianID { get; set; }
[Column("MotherID")]
public int? MotherID { get; set; }
[Column("FatherID")]
public int? FatherID { get; set; }
public IEnumerable<Person> Children { get
{
return context.Person.Where(p => p.GuardianID == this.ID || p.Father == this.ID || p.MotherID == this.ID).ToList();
}
}
}
#using Person_MVC.Models
#model IEnumerable<Person>
<ul>
#foreach (Person person in Model.OrderBy(p => p.PersonNumber))
{
<li id="Pnl_#Person.ID" data-jstree='{"type":"Person"}' data-Personkey="#Person.ID.ToString()">
#Person.Name
#if (Person.Children != null && Person.Children.Count() > 0)
{
#Html.Partial("PersonTree", Person.Children)
}
</li>
}
</ul>
I am currently following this tutorial for Concurrency Handling.
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application
However, the DbUpdateConcurrencyException is not raised in my case. I'm using Database first approach in EF 5.0
I have Carrier object with 0..1 relationship with Address & Contact objects.
I have created the a RowVersion field in the Carrier table .
My code is as follows:
public Carrier UpdateCarrier(Carrier carrier)
{
try
{
var entry = ariesConfigContext.Entry<Carrier>(carrier);
if(entry.State == System.Data.EntityState.Detached)
{
var attachedEntity = ariesConfigContext.Carriers.Include(con => con.Contact).Include(a => a.Address).Single(c => c.CarrierID == carrier.CarrierID);
if(attachedEntity != null)
{
var attachedEntry = ariesConfigContext.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(carrier);
attachedEntity.Contact = carrier.Contact;
attachedEntity.Address = carrier.Address;
}
else
{
entry.State = System.Data.EntityState.Modified;
}
}
ariesConfigContext.SaveChanges();
}
catch(DbUpdateConcurrencyException ex)
{
//do something
}
return carrier;
}
My Model is as follows:
namespace Aries.Domain.Models.AriesConfigDB
{
using System;
using System.Collections.Generic;
public partial class Carrier
{
public Carrier()
{
this.UserProfiles = new HashSet<UserProfile>();
}
public int CarrierID { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Memo { get; set; }
public string DBServerName { get; set; }
public string DBName { get; set; }
public string DBUser { get; set; }
public string DBPassword { get; set; }
public Nullable<int> AddressID { get; set; }
public Nullable<int> ContactID { get; set; }
public bool IsDeleted { get; set; }
public byte[] RowVersion { get; set; }
public virtual Address Address { get; set; }
public virtual Contact Contact { get; set; }
public virtual ICollection<UserProfile> UserProfiles { get; set; }
}
}
My View is:
#model Aries.Domain.Models.AriesConfigDB.Carrier
<div>
<div class="message-error">
#if (TempData["ErrorMessage"] != null)
{
<p>#TempData["ErrorMessage"]</p>
}
</div>
#Html.HiddenFor(model => model.CarrierID)
#Html.HiddenFor(model => model.RowVersion)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Abbreviation)
</div>
....
....
I'm unable to get the Exception to be raised. Any help is appreciated.
UPDATE:
I already have a Metadata class for Carrier as below and I've added the [Timestamp] attribute there.
public class CarrierMetadata
{
public int CarrierID { get; set; }
[Required]
[MaxLength(255, ErrorMessage = "Carrier Name must be 255 characters or less")]
[Display(Name = "Carrier Name")]
public string Name { get; set; }
....
....
[Required]
[ConcurrencyCheck]
[Timestamp]
public byte[] RowVersion { get; set; }
}
And my Carrier class has the following attribute:
[MetadataType(typeof(CarrierMetadata))]
public partial class Carrier
{
}
But it still doesn't work.
Hi I've been stuck to long on this problem. I've looked at a lot of examples but i cant find what im looking for. Any help is appreciated.
I use the Code-First approach.
I've enabled migration and the database is fine [Student] - [StudentCourse] - [Course].
Scenario: I have two entites -> Student
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Course> Courses { get; set; }
}
And Course
public class Course
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual List<Student> Students { get; set; }
}
Nothing fancy about that... Ive created a ViewModel ->
public class StudentCourseViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<Course> Courses { get; set; }
}
View:
#model Project.Web.Models.StudentCourseViewModel #{
ViewBag.Title = "Edit"; }
Edit
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Student</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Courses)
</div>
<div class="editor-field">
#for (int i = 0; i < Model.Students.Count(); i++)
{
<div style="border: dotted 1px; padding: 5px; margin: 10px;">
#Html.HiddenFor(s => s.Students[i].Id)
#Html.LabelFor(s => s.Students[i].Name[i + 1])
#Html.EditorFor(s => s.Students[i].Name)
</div>
}
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset> }
Controller Action:
[HttpPost]
public ActionResult Edit(CourseStudentViewModel model)
{
var course = db.Courses.Find(model.CourseId);
course.Name = model.CourseName;
course.Description = model.CourseDescription;
course.Students = model.Students;
if (ModelState.IsValid)
{
db.Entry(course).State = System.Data.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
(Maby this is were i go wrong...)
Anyway, I want to create a new Student with optional many courses (textboxes -> courseName)
How should i do this?
The main issue is that i always get null values (student is fine, List of courses = NULL) back from my view [httpPost]Create -action.
I'm in need of guidance how to make this approach possible.
Thx J!
Your entities are not setup correctly for a many-to-many relationship. You need another entity to handle the many-to-many mapping. It would look something like this.
public class StudentsToCourses
{
public int StudentId {get; set;}
public int CourseId {get; set;}
public virtual Student Student {get; set;}
public virtual Course Course {get; set;}
}
Then your student model should be changed to this.
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<StudentsToCourses> Courses { get; set; }
}
And your coursed model changed to this.
public class Course
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual List<StudentsToCourses> Students { get; set; }
}
You also need to setup the foreign key relationship using the Fluent API. It would look something like this.
public class StudentsToCoursesConfiguration : EntityTypeConfiguration<StudentsToCourses>
{
internal StudentsToCoursesConfiguration ()
{
this.HasKey(p => new {p.StudentId, p.CourseId});
this.HasRequired(p => p.Student)
.WithMany(p => p.Courses)
.HasForeignKey(p => p.StudentId);
this.HasRequired(p => p.Course)
.WithMany(r => r.Students)
.HasForeignKey(p => p.CourseId);
}
}
I am using Entity Framework 4.1 code first.
I had a table in the database with the name MaritalStatus. I deleted it and created a new table in its place called MaritalStatuses. Whenever I try to get all the records from the table I get an error:
Invalid object name 'dbo.MaritalStatus'.
The query that it is trying to execute is:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[IsActive] AS [IsActive]
FROM [dbo].[MaritalStatus] AS [Extent1]}
Why would it still be looking for table MaritalStatus that I deleted? Can it be possible that it is cached somewhere? I dropped the whole database and recreated it via scripts. Still no luck. Maybe it has an issue when it comes to the "es" part of the name?
Context class:
public class HefContext : DbContext
{
public DbSet<Bank> Banks { get; set; }
public DbSet<AccountType> AccountTypes { get; set; }
public DbSet<MaritalStatus> MaritalStatuses { get; set; }
}
View model (with partial properties):
public class EditGrantApplicationViewModel
{
public int Id { get; set; }
public string EmployeeNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int MaritalStatusId { get; set; }
public IEnumerable<MaritalStatus> MaritalStatuses { get; set; }
public int BankId { get; set; }
public IEnumerable<Bank> Banks { get; set; }
public int AccountTypeId { get; set; }
public IEnumerable<AccountType> AccountTypes { get; set; }
}
Dropdown list in view for MaritalStatuses:
<td><label>Marital Status:</label> <span class="red">**</span></td>
<td>
#Html.DropDownListFor(x => x.MaritalStatusId, new SelectList(Model.MaritalStatuses, "Id", "Name", Model.MaritalStatusId), "-- Select --")
#Html.ValidationMessageFor(x => x.MaritalStatusId)
</td>
Controller:
public ActionResult Create()
{
EditGrantApplicationViewModel viewModel = new EditGrantApplicationViewModel
{
MaritalStatuses = maritalStatusService.GetAll(),
Banks = bankService.GetAll(),
AccountTypes = accountTypeService.GetAll()
};
return View(viewModel);
}
Service:
public IEnumerable<MaritalStatus> GetAll()
{
return maritalStatusRepository.GetAll();
}
Repository:
HefContext db = new HefContext();
public IEnumerable<MaritalStatus> GetAll()
{
return db.MaritalStatuses;
}
Model class:
public class MaritalStatus
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
You may have renamed the table in your database, but your Model class is still tied to the old name. You need to map the entity to the desired table name in the OnModelCreating method of your DbContext object
public class HefContext : DbContext
{
public DbSet<Bank> Banks { get; set; }
public DbSet<AccountType> AccountTypes { get; set; }
public DbSet<MaritalStatus> MaritalStatuses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MaritalStatus>().ToTable("MaritalStatuses");
}
}
Update:
Apparently EF code first has some issues with the pluralization of some table names, such as Status. Out of curiosity I tested a few others and found several which also had this same issue.
I guess this is wrong:
public DbSet<MaritalStatus> MaritalStatuses { get; set; }
Should be:
public DbSet<MaritalStatuses> MaritalStatuses { get; set; }