3

我很难让我的导航属性在 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 的列表。这很好,这是应该的。但是,如果我停止程序并重新运行它,当我查看 DbSet 时,仍然有 1 个 Parent,但它的“Children”属性已设置为 null。

总而言之,保存后立即值是正确的,但是一旦我重新加载数据库上下文,这些值就会丢失(空值)。我正在运行启用了 LazyLoading 的最新 EF。

应该注意的是,如果我使用 .Include(),它将使用正确的 NamedChild 列表填充那些空值,但我需要它来使用 LazyLoading。

4

2 回答 2

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

于 2013-07-08T19:11:31.113 回答
1

虽然我认为这在技术上并不重要,但我注意到 EF 似乎更喜欢ICollections其他列表/数组类型。尝试:

public virtual ICollection<NamedChild> Children {get; set;}

另外,我对您尝试使用自定义构造函数实现的目标有些困惑。似乎您所做的只是初始化实例上的属性。如果是这种情况,则不需要自定义构造函数。只需使用类初始化语法:

x => new NamedChild { ChildId = x.ChildId, Name = "" }
于 2013-07-08T18:38:26.620 回答