tee*_*nup 47 linq performance linq-to-entities entity-framework asp.net-mvc-2
我在我的个人资料页面使用以下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;
Run Code Online (Sandbox Code Playgroud)
它有一个长对象图并使用许多包含.它现在运行得很好,但是当网站有很多用户时,它会影响性能吗?
我应该用其他方式吗?
Lad*_*nka 84
带有includes的查询返回单个结果集,包含的数量会影响大数据集从数据库服务器传输到Web服务器的大小.例:
假设我们有一个实体Customer (Id, Name, Address)和一个实体Order (Id, CustomerId, Date).现在我们想用她的订单查询客户:
var customer = context.Customers
                      .Include("Orders")
                      .SingleOrDefault(c => c.Id == 1);
Run Code Online (Sandbox Code Playgroud)
结果数据集将具有以下结构:
 Id | Name | Address | OrderId | CustomerId | Date 
---------------------------------------------------
  1 |  A   |   XYZ   |    1    |     1      | 1.1.
  1 |  A   |   XYZ   |    2    |     1      | 2.1.
Run Code Online (Sandbox Code Playgroud)
这意味着Cutomers每个都重复数据Order.现在让我们用另一个实体扩展示例 - 'OrderLine(Id,OrderId,ProductId,Quantity)andProduct(Id,Name)`.现在我们想要查询客户的订单,订单行和产品:
var customer = context.Customers
                      .Include("Orders.OrderLines.Product")
                      .SingleOrDefault(c => c.Id == 1);
Run Code Online (Sandbox Code Playgroud)
结果数据集将具有以下结构:
 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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,数据变得非常复杂.通常每个包含到引用导航属性(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();
Run Code Online (Sandbox Code Playgroud)
示例LoadProperty:
var customer = context.Customers
                      .SingleOrDefault(c => c.Id == 1);
context.LoadProperty(customer, c => c.Orders);
Run Code Online (Sandbox Code Playgroud)
此外,您应始终只加载您真正需要的数据.
编辑:我刚刚在Data UserVoice上创建了提案,以支持其他热切加载策略,其中急切加载的数据将在其他结果集中传递(由同一数据库往返中的单独查询创建).如果您发现此改进有趣,请不要忘记投票支持该提案.
Sam*_*ath 15
您可以通过从数据库创建2个或更多小数据请求来提高许多包含的性能,如下所示.
根据我的经验,只能给出每个查询最多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();
Run Code Online (Sandbox Code Playgroud)
以上将通过使用更多数据到数据库来从数据库中提取小数据集.
我希望这会对你有所帮助.
是的,它会的.如果扩展主表行上的多个详细信息行,请避免使用Include.
我相信EF将查询转换为一个大型连接而不是几个查询.因此,您最终会在详细信息表的每一行上复制主表数据.
例如:Master - > Details.比如说,master有100行,Details有5000行(每个master有50行).
如果延迟加载详细信息,则返回100行(size:master)+ 5000行(size:details).
如果使用.Include("Details"),则返回5000行(size:master + details).基本上,主要部分重复50次.
如果包含多个表,它会向上相乘.
检查EF生成的SQL.