简体   繁体   中英

Entity Framework - Navigation Properties Not Saving

I'm having huge difficulties getting my navigation properties to work in EF Code First. As an abstracted example, I have:

public class Parent{
    public int ParentID {get; set;}
    public virtual List<NamedChild> Children {get; set;}
    public Parent(){}
    public void Init(int ParentID, List<UnnamedChild> Children){
        this.ParentID = ParentID;
        this.Children = Children.ConvertAll(x => new NamedChild(x, ""));
    }
}

public class NamedChild{
    public int ChildID {get; set;}
    public string Name {get; set;}
    public NamedChild(UnnamedChild c, string Name){
        this.ChildID = c.ChildID;
        this.Name = Name;
    }
}

public class UnnamedChild{
    public int ChildID {get; set;}
    public UnnamedChild(int ChildID){
        this.ChildID = ChildID;
    }
}

and then later...

List<UnnamedChild> children = GetChildrenFromSomewhere();
Parent p = db.Parents.Create();
p.Init(1, children);
db.Parents.Add(p);
db.SaveChanges();

Now if I'm debugging I can look into the current DbSet and it shows that there is 1 Parent, and its "Children" property is set to a List of 2 NamedChild. This is good, this is what it should be. However, if I stop the program and re-run it, when I look in the DbSet there is still 1 Parent, but its "Children" property has been set to null.

In summary, immediately after saving it the values are right, but as soon as I re-load the DB Context those values are missing (nulls). I am running the most recent EF with LazyLoading enabled.

It should be noted that if I use .Include(), it will populate those null values with the proper NamedChild list, but I need this to work with LazyLoading.

Although I don't think it should technically matter, I've noticed that EF seems to prefer ICollections to other list/array types. Try:

public virtual ICollection<NamedChild> Children {get; set;}

Also, I'm a little confused about what you're trying to achieve with your custom constructors. It seems that all you're doing is initializing the properties on the instance. If that's the case, a custom constructor is not needed. Just use the class initialization syntax:

x => new NamedChild { ChildId = x.ChildId, Name = "" }

I think EF is probably unable to create a proxy for NamedChild objects, and can't perform any lazy loading as a result.

One of the requirements for creating a proxy class is that your POCO must have a public/protected constructor without parameters.

This may solve your problem:

public class NamedChild
{
    public int ChildID {get; set;}
    public string Name {get; set;}

    protected NamedChild() {}

    public NamedChild(UnnamedChild c, string Name)
    {
        this.ChildID = c.ChildID;
        this.Name = Name;
    }
}

I believe you already meet all the other requirements for lazy loading proxies.

Full Requirements here: http://msdn.microsoft.com/en-us/library/vstudio/dd468057%28v=vs.100%29.aspx

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