简而言之:
如果代码访问导航属性并且请求的数据未加载到内存中并且延迟加载被禁用,是否有办法让EF抛出异常?
再长一点:
我正在使用Entity Framework 4(模型优先)并禁用了延迟加载。之前,如果我运行类似下面的内容,代码将运行良好但速度很慢,因为每次调用customer.Orders都会导致执行新的SQL查询:
int totalValue = 0;
foreach(var customer in efContext.Customers)
foreach (var order in customer.Orders)
totalValue += order.Value;
我想完全禁用延迟加载,以防止在我正在处理的代码库中引入这样的代码。我想要发生的是,当代码执行customer.Orders时,应抛出异常,说明“实体未加载。懒惰加载已关闭”。但相反,订单列表只是空的,因为订单尚未加载。
我觉得这种行为也可能有问题,只是以与延迟加载不同的方式。负责检查每个客户是否有联系人的开发人员可以编写如下内容:
if (customer.Contact != null)
throw new BlablablaException("Customer lacks contact");
但是如果禁用延迟加载,则customer.Contact将始终为null,并且开发人员可能会认为他的代码正常运行。当然,他应该正确地完成他的工作并测试两种情况(联系现有的,联系不存在)但是如果抛出异常会更加清楚。
在我看来,如果我尝试访问不可用的数据而只返回一个空列表,实体框架不会抛出异常,这似乎很奇怪。
这种行为有解释吗?有没有办法在调用导航属性并且数据不可用时使EF抛出异常?
答案 0 :(得分:0)
您可以测试每个条目以确保它已加载。
如果是集合:
model.Entry(customer).Collection(c => c.Customers).IsLoaded
如果它不是一个集合:
model.Entry(customer).Reference(c => c.Customer).IsLoaded
但是,我认为如果你在迭代之前急切地加载你的集合会更好,保证集合被加载,而不是担心集合是否被加载:
foreach(var customer in efContext.Customers.Include(c => c.Orders))