简体   繁体   中英

asp.net mvc 5, entity framework 6 code first, Identity 2.0. How to set navigation property to model object?

It should be something simple, not sure why I couldn't find the solution on the web. Maybe it's specific to EF6 or ASP Identity or, maybe I'm entering wrong search key words.

To simplify things, let's say I have two model classes Teacher and Kid; One kid can be assigned only to one teacher, but one teacher can have many kids. It's multi-user environment, so each Kid and each Teacher belong to particular user. As I'm using code first, my database is constructed from these model classes:

public class Kid
{
    [Required]
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public virtual Teacher { get; set; }    
    [Required]
    public virtual ApplicationUser User { get; set; }
}

public class Teacher
{
    [Required]
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    public virtual ICollection<Kid> Kids { get; set; }
    [Required]
    public virtual ApplicationUser User { get; set; }
    }

I have a view for adding new kid with: Textbox for Kid's name; Dropdown with list of Teachers

So, I'm creating a data transfer object, specifically for that view:

public class AddNewKidViewDTO
{
    public string Name {get; set;}
    public IEnumerable<SelectListItem> Teachers { get; set; }
    public int SelectedTeacherId { get; set; }
}

Form gets submitted and I get my populated AddNewKidViewDTO model.

Now, I need to insert a new Kid into the database. So, I map AddNewKidViewDTO properties to my Kid model properties one by one:

public void InsertNewKid {AddNewKidViewDTO addNewKidViewDTO}
{
    Kid kid = new Kid();
    kid.Name = AddNewKidViewDTO.Name;
    // here comes the question. How do I set Kid.Teacher and Kid.User?
}

UPDATE 1

I'm NOT asking how to get selected teacher id. I need to know how to assign navigation property to model object (using that id).

UPDATE 2:

If I get current user object like this:

ApplicationUser user = usermanager.FindById(User.Identity.GetUserId<int>());

And then attach it to Kid:

Kid.User = user;

On Kid insert, it throws exception:

The member with identity 'mynamespace.DAL.Kid_User' does not exist in the metadata collection.

Any help appreciated.

AddNewKidViewDTO.Teachers.FirstOrDefault(t=>t.Selected).Value

above code will give selected teacher id.

Can u post the Kid model

public void InsertNewKid {AddNewKidViewDTO addNewKidViewDTO}
{
    Kid kid = new Kid();
    kid.Name = AddNewKidViewDTO.Name;
    kid.Teacher = yourdatacontext.Teachers.Find(addNewKidViewDTO.SelectedTeacherId);
    // The context.Savechanges() can be done either here or in your actionlink
}

You should be able to do the same with user assuming you know the appropriate id. It is also possible to search it using the .where method if you don't have the id in hand. Exemple:

kid.User = context.Users.Where(x => x.Name == "whatever string").FirstOrDefault<User>();

This can be done with any attribute.

Considering your database has properly generated the 1 to many relationship, the kid should automatically be added into the "parent" teacher's kids collection.

However I am concerned about the [Required] for

public virtual ICollection<Kid> Kids { get; set; }

A kid is dependant on the existence of a teacher however I don't really see the point of the dependency being both ways.

Teacher constructor to be added right into the model class:

public Teacher()
        {
            this.Kids = new HashSet<Kid>();
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM