实体框架-导航属性未保存
本文关键字:保存 属性 导航 框架 实体 | 更新日期: 2023-09-27 18:21:36
我在让导航属性在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。
总之,在保存后,值是正确的,但一旦我重新加载DB上下文,这些值就会丢失(null)。我正在运行启用了LazyLoading的最新EF。
需要注意的是,如果我使用.Include(),它会用正确的NamedChild列表填充这些null值,但我需要这样才能使用LazyLoading。
我认为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
虽然我认为这在技术上并不重要,但我注意到EF似乎更喜欢ICollections
而不是其他列表/数组类型。尝试:
public virtual ICollection<NamedChild> Children {get; set;}
此外,我对您试图用自定义构造函数实现的目标有点困惑。您所做的似乎只是初始化实例上的属性。如果是这种情况,则不需要自定义构造函数。只需使用类初始化语法:
x => new NamedChild { ChildId = x.ChildId, Name = "" }