EntityFramework中的ObjectSet包含多less个可用于保持性能?

我正在使用以下的LINQ查询我的个人资料页面:

var userData = from u in db.Users .Include("UserSkills.Skill") .Include("UserIdeas.IdeaThings") .Include("UserInterests.Interest") .Include("UserMessengers.Messenger") .Include("UserFriends.User.UserSkills.Skill") .Include("UserFriends1.User1.UserSkills.Skill") .Include("UserFriends.User.UserIdeas") .Include("UserFriends1.User1.UserIdeas") where u.UserId == userId select u; 

它有一个很长的对象图,并使用许多包括。 它现在运行的很完美,但是当网站有很多用户时,会不会影响性能呢?

我应该以其他方式做吗?

带有包含的查询返回单个结果集,包含的数量会影响数据集从数据库服务器传输到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) and 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 )将添加新列,并且每个列都包含一个集合导航属性(示例中的OrdersOrderLines )将添加新列并复制已包含集合中每行的已创build行。

这意味着你的例子可以很容易地有数百列和数千行,这是很多数据传输。 正确的方法是创build性能testing,如果结果不能满足您的期望,您可以通过自己的查询或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上创build提案,以支持额外的预先加载策略,其中预先加载的数据将被传递到附加结果集中(由同一数据库往返中的单独查询创build)。 如果你觉得这个改进有趣,不要忘了投票。

您可以通过创build2个或更多来自下面的数据库的小数据请求来提高许多包括性能。

根据我的经验, 每个查询最多只能给出2个以下的结果,这样会给性能带来不好的影响。

 var userData = from u in db.Users .Include("UserSkills.Skill") .Include("UserIdeas.IdeaThings") .FirstOrDefault(); userData = from u in db.Users .Include("UserFriends.User.UserSkills.Skill") .Include("UserFriends1.User1.UserSkills.Skill") .FirstOrDefault(); 

以上将通过使用更多的旅行到数据库从数据库中带来小的数据集。

我已经用自己的经验写了博客文章

我希望这对你有帮助。

是的,它会。 如果在主表行上展开多个详细信息行,请避免使用“包含”。

我相信EF将查询转换成一个大的联接,而不是几个查询。 因此,您最终将在详细信息表的每一行上复制主表数据。

例如:Master – > Details。 说,主人有100行,详细信息有5000行(每个主人50)。

如果您延迟加载细节,则返回100行(size:master)+ 5000行(size:details)。

如果使用.Include(“Details”),则返回5000行(size:master + details)。 基本上,主部分被复制超过50次。

如果包含多个表格,它会向上扩展。

检查EF生成的SQL。

我build议你进行负载testing,并测量压力下的网站性能。 如果你对每个请求执行复杂的查询,你可能会考虑caching一些结果。

包含的结果可能会改变:它由调用include方法的实体来决定。

就像Ladislav Mrnka提出的例子一样,假设我们有一个实体

客户(身份证,姓名,地址)

映射到这个表格:

 Id | Name | Address ----------------------- C1 | Paul | XYZ 

和实体订单(Id,CustomerId,Total)

映射到这个表格:

 Id | CustomerId | Total ----------------------- O1 | C1 | 10.00 O2 | C1 | 13.00 

关系是一个客户许多订单


示例1:客户=>订单

 var customer = context.Customers .Include("Orders") .SingleOrDefault(c => c.Id == "C1"); 

Linq将被翻译成一个非常复杂的SQL查询。

在这种情况下,查询将产生两条logging,关于客户的信息将被复制。

  Customer.Id | Customer.Name | Order.Id | Order.Total ----------------------------------------------------------- C1 | Paul | O1 | 10.00 C1 | Paul | O2 | 13.00 

示例2:Order => Customer

 var order = context.Orders .Include("Customers") .SingleOrDefault(c => c.Id == "O1"); 

Linq将在一个简单的sqljoin中进行翻译。

在这种情况下,查询将只产生一个没有重复信息的logging:

  Order.Id | Order.Total | Customer.Id | Customer.Name ----------------------------------------------------------- O1 | 10.00 | C1 | Paul