3

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.

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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 = "" } 

1 Comment

That is true. It should not make a difference though.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.