最近,我们为实体框架关闭了Lazy加载和代理生成。在此之前,在我们对EF进行了新的更改之后,我们将收到整个对象图。我现在正在做的是,在提交之后,我在存储库上调用FindById方法来获取新对象(我将导航属性包含在newley创建的对象中)。我的问题是,这是创建后的标准做法还是客户应负责第二次调用服务来获取新创建的对象?
保存服务方法:
public SomeObject Create(SomeObject someObject)
{
_repository.Add(someObject);
_repository.UnitOfwork.Commit()
//this did not exist when lazy loading and proxy generation were enabled.
var newObject = _repository.FindById(someObject.Id);
return newObject;
//Before we would jsut return the created object because everything was loaded.
//return someObject
}
我只是想知道在禁用延迟加载和代理创建创建对象后这是否是最佳实践。我很想知道其他开发人员如何处理这个问题。
答案 0 :(得分:2)
在我们将jsut返回创建的对象之前,因为一切都是 加载。
不知何故,我怀疑这是真的。如果您调用SaveChanges
EF不执行查询以加载导航属性,无论您是否使用延迟加载。例如:
假设您的订单带有对客户的导航参考,并且数据库中已经是Id = 1的客户。现在您创建了一个订单(启用了延迟加载):
var order = context.Orders.Create();
order.CustomerId = 1;
context.Orders.Add(order);
context.SaveChanges();
bool isCustomerLoaded = context.Entry(order).Reference(o => o.Customer).IsLoaded;
isCustomerLoaded
将为false
- 除非客户1已经在上下文中,但是该属性也将在没有延迟加载的情况下填充(“关系修正”)。当然,只要您访问order.Customer
,它就会因延迟加载而被加载,但之后会发生,而与SaveChanges
无关。
如果你的代码是个好主意,取决于返回对象的使用方式和消费者期望的方式。通常,没有延迟加载的延迟加载的最接近替换是显式加载,因为两个加载策略执行单个查询以加载导航属性。当然,你必须在消费者端引入额外的代码来加载属性,而使用延迟加载“它只是工作”,当你使用属性并且查询发生在代理对象的重载属性getter的幕后。显式加载看起来像这样:
context.Entry(order).Reference(o => o.Customer).Load();
// or for collections
context.Entry(order).Collection(o => o.OrderItems).Load();
您必须在第一次访问导航属性的位置调用它。
如果您事先知道从Create
方法返回的对象需要所有导航属性,那么您可以按照建议的方式加载它们。但与延迟加载相比,这肯定是数据库访问模式的一个变化:Eager加载只需要一个查询来加载整个对象图,但这是一个可能非常昂贵的查询,在DB中有很多JOIN和许多数据回。而延迟加载和显式加载将发出多个查询,但返回的数据更少的查询更简单。如果不考虑模型细节和进行测量,就不可能说什么更好。