EF 4.4中的DbContext和导航属性

时间:2013-02-06 13:09:36

标签: entity-framework dbcontext

将项目从EntityObject生成器切换到DbContext后,我在新对象上使用了一些导航属性遇到了问题。我花了很多时间研究这个问题,而且我没有接近理想的解决方案。

首先,生成的类定义:

public partial class Category
{
    public Category()
    {
        this.Limits = new HashSet<Limit>();
    }

    public int CategoryId {get; set;}
    public string Name {get; set;}
    public virtual ICollection<Limit> Limits { internal get; set; }
}

public partial class Limit
{
    public int CategoryId {get; set;}
    public string Description {get; set;}
    internal virtual Category Category { get; set; }
}

我使用以下代码在集成测试期间创建测试数据:

using (GFCAMDataContext db = new GFCAMDataContext())
{
    limit = new Limit()
    {
        CategoryId = testData.CategoryId,
        Description = "SignerController.Update"
    };

    db.Limits.Add(limit);
    db.SaveChanges();
}

没有任何其他更改,我新创建的Limit对象的Limit.Category属性不会返回任何内容。但是,如果在调用SaveChanges之前从DbContext查询所需的类别,则我的新限制上的导航属性将开始返回关联的类别。使用ObjectContext,可以更新Category属性,而无需我的任何干预。

我希望与ObjectContext具有相同的行为,但我似乎无法找到实现此目标的方法。我见过几个建议的解决方案:

  • 将导航属性设为公开。这具有相同的行为,并且不可取,因为公共导航属性可能在序列化期间导致问题,并且在我的业务层之外不需要。

  • 将所有属性设为公共虚拟,并使用DbSet.Create确保代理创建。这导致了相同的行为,并且不一定是理想的,因为我有动态创建实例的代码(即我在创建实体实例时无法访问DbSet)。

有没有人对这个问题的解决方案有任何建议?

1 个答案:

答案 0 :(得分:0)

一种解决方案是显式加载嵌套实体:

db.SaveChanges();
db.Entry(person).Reference(z => z.Category).Load();

启用代理时,另一个选项确实是调用DbSet.Create<T>()。如果在创建实体时无法访问DbSet实例,则可能需要在存储库接口中公开允许该实例的公共方法。例如:

public interface IRepository<T>
{
    T Add(T entity);

    T GetById(...);

    void SaveChanges();

    ...

    T CreateInstance(); // Concrete implementation have access to DbSet and uses DbSet.Create<T>()
}