将项目从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)。
有没有人对这个问题的解决方案有任何建议?
答案 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>()
}