包含包含的查询返回单个结果集,包含的数量会影响大数据集从数据库服务器传输到 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.
这意味着对于每个Order 重复Cutomers 数据。现在让我们用另一个实体扩展该示例 - 'OrderLine (Id, OrderId, ProductId, Quantity)andProduct (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);
此外,您应该始终只加载您真正需要的数据。
编辑:我刚刚创建了proposal on Data UserVoice 以支持额外的预加载策略,其中预加载的数据将在额外的结果集中传递(由同一数据库往返中的单独查询创建)。如果您觉得这项改进很有趣,请不要忘记为该提案投票。