4

简而言之:

如果代码访问导航属性并且请求的数据未加载到内存中并且延迟加载被禁用,是否有办法使 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 将始终为空,开发人员可能会认为他的代码可以正常工作。当然,他应该正确地完成他的工作并测试两种情况(联系存在,联系不存在),但如果抛出异常会更清楚。

在我看来,如果我尝试访问不可用的数据而只是返回一个空列表,Entity Framework 不会引发异常,这似乎很奇怪。

这种行为有解释吗?当调用导航属性并且数据不可用时,有没有办法让 EF 抛出异常?

4

1 回答 1

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))
于 2012-09-21T18:01:20.160 回答