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

时间:2013-07-08 18:25:07

标签: c# asp.net-mvc asp.net-mvc-4 entity-framework-5 lazy-loading

让我的导航属性在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。

2 个答案:

答案 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