实体框架-导航属性未保存

本文关键字:保存 属性 导航 框架 实体 | 更新日期: 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 = "" }