让我的导航属性在EF Code First中工作时遇到了很大的困难。作为一个抽象的例子,我有:
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;
}
}
然后再......
List<UnnamedChild> children = GetChildrenFromSomewhere();
Parent p = db.Parents.Create();
p.Init(1, children);
db.Parents.Add(p);
db.SaveChanges();
现在,如果我正在调试,我可以查看当前的DbSet,它显示有1个Parent,其“Children”属性设置为2 NamedChild的List。这很好,这应该是它应该是的。但是,如果我停止程序并重新运行它,当我查看DbSet时,仍然有1个Parent,但其“Children”属性已设置为null。
总之,在保存之后,值立即生效,但是一旦我重新加载数据库上下文,这些值就会丢失(空值)。我正在运行最近启用了LazyLoading的EF。
应该注意的是,如果我使用.Include(),它将使用正确的NamedChild列表填充这些空值,但我需要使用它来使用LazyLoading。
答案 0 :(得分:1)
虽然我认为它在技术上不重要,但我注意到EF似乎更喜欢ICollections
到其他列表/数组类型。尝试:
public virtual ICollection<NamedChild> Children {get; set;}
此外,我对您尝试使用自定义构造函数实现的目标感到有些困惑。看起来您正在做的就是初始化实例上的属性。如果是这种情况,则不需要自定义构造函数。只需使用类初始化语法:
x => new NamedChild { ChildId = x.ChildId, Name = "" }
答案 1 :(得分:1)
我认为EF可能无法为NamedChild
对象创建代理,因此无法执行任何延迟加载。
创建代理类的一个要求是您的POCO必须有一个没有参数的public/protected
构造函数。
这可以解决您的问题:
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;
}
}
我相信您已经满足了延迟加载代理的所有其他要求。
此处的完整要求: http://msdn.microsoft.com/en-us/library/vstudio/dd468057%28v=vs.100%29.aspx