使用 includes 的查询会返回一个结果集,而包含的数量会影响从数据库服务器传输到 web 服务器的数据集大小。例如:
假设我们有一个实体 Customer (Id, Name, Address)
和一个实体 Order (Id, CustomerId, Date)
。现在我们想查询一位客户及她的订单:
var customer = context.Customers
.Include("Orders")
.SingleOrDefault(c => c.Id == 1);
生成的数据集将具有以下结构:
Id | Name | Address | OrderId | CustomerId | Date
---------------------------------------------------
1 | A | XYZ | 1 | 1 | 1.1.
1 | A | XYZ | 2 | 1 | 2.1.
这意味着每个订单都会重复列出Customers
的数据。现在我们通过添加其他实体来扩展示例 - 'OrderLine (Id, OrderId, ProductId, Quantity)和
Product (Id, Name)'。现在我们想要查询一个客户及其订单,订单行和产品:
var customer = context.Customers
.Include("Orders.OrderLines.Product")
.SingleOrDefault(c => c.Id == 1);
生成的数据集将具有以下结构:
Id | Name | Address | OrderId | CustomerId | Date | OrderLineId | LOrderId | LProductId | Quantity | ProductId | ProductName
------------------------------------------------------------------------------------------------------------------------------
1 | A | XYZ | 1 | 1 | 1.1. | 1 | 1 | 1 | 5 | 1 | AA
1 | A | XYZ | 1 | 1 | 1.1. | 2 | 1 | 2 | 2 | 2 | BB
1 | A | XYZ | 2 | 1 | 2.1. | 3 | 2 | 1 | 4 | 1 | AA
1 | A | XYZ | 2 | 1 | 2.1. | 4 | 2 | 3 | 6 | 3 | CC
正如您所看到的,数据会出现相当多的重复。通常来说,每个引用导航属性(例如示例中的Product
)都会添加新列,而每个集合导航属性(例如示例中的Orders
和OrderLines
)都会添加新列,并为包含的每一行复制已创建的行。
这意味着您的示例可能会有数百列和数千行,这是需要传输的大量数据。正确的方法是创建性能测试,如果结果不能满足您的期望,您可以修改查询并单独通过它们自己的查询或LoadProperty
方法加载导航属性。
单独查询的示例:
var customer = context.Customers
.Include("Orders")
.SingleOrDefault(c => c.Id == 1);
var orderLines = context.OrderLines
.Include("Product")
.Where(l => l.Order.Customer.Id == 1)
.ToList();
LoadProperty
的示例:
var customer = context.Customers
.SingleOrDefault(c => c.Id == 1);
context.LoadProperty(customer, c => c.Orders);
此外,您应该始终只加载实际需要的数据。
编辑:我刚刚在Data UserVoice上创建了提案,以支持额外的急切加载策略,在同一数据库查询中创建单独查询所产生的附加结果集来传递急切加载的数据。如果您觉得这个改进很有趣,请不要忘记为该提案投票。