简体   繁体   English

在Entity Framework中使用简单查询,性能非常差

[英]Very poor performance with a simple query in Entity Framework

So I have a very simple structure: 所以我有一个非常简单的结构:

  • I have Orders that have a unique OrderNumber 我的订单有一个唯一的OrderNumber
  • Orders have many OrderRows 订单有很多OrderRows
  • OrderRows have many RowExtras that have 2 fields, position (the sequence number of the RowExtra within the OrderRow) and Info, which is a string. OrderRows有许多RowExtras,它们有2个字段,position(OrderRow中RowExtra的序列号)和Info,它是一个字符串。 More often than not, an OrderRow does not have more than one RowExtra. OrderRow通常没有多个RowExtra。

(Don't mind the silly structure for now, it's just how it is). (现在不要介意愚蠢的结构,它就是这样的)。

So now I get a list of objects that have three properties: 所以现在我得到一个具有三个属性的对象列表:

  • OrderNumber 订单号
  • Position 位置
  • Info 信息

What I want to do is simply 1) check if the RowExtra with the given OrderNumber/Position -pair exists in the database and if so, 2) update the Info-property. 我想要做的只是1)检查数据库中是否存在具有给定OrderNumber / Position -pair的RowExtra,如果存在,则2)更新Info-property。

I have tried a few different ways to accomplish this with very poor results at best. 我尝试了几种不同的方法来实现这一点,结果非常糟糕。 The solutions loop through the list of objects and issue a query such as 解决方案循环遍历对象列表并发出诸如的查询

myContext.RowExtras.Where(x => x.Position == currentPosition &&
                          x.OrderRow.Order.OrderNumber == currentOrderNumber) 

or going from the other side 或从另一边走

myContext.Orders.Where(x => x.OrderNumber == currentOrderNumber)
                .SelectMany(x => x.OrderRows)
                .SelectMany(x => x.RowExtras)
                .Where(x => x.Position == currentPosition)

and then check if the count equals to 1 and if so, update the property, otherwise proceed to next item. 然后检查计数是否等于1,如果是,则更新属性,否则继续下一个项目。

I currently have roughly 4000 RowExtras in the database and need to update about half of them. 我目前在数据库中有大约4000个RowExtras,需要更新其中一半。 These methods make the procedure take several minutes to complete, which is really not acceptable. 这些方法使程序需要几分钟才能完成,这是不可接受的。 What I don't understand is why it takes such a long time, because the SQL-clause that returns the required RowExtra would be quite easy to write manually (with just 2 joins and 2 conditions in the where-part). 我不明白为什么需要这么长时间,因为返回所需RowExtra的SQL子句很容易手动编写(在where-part中只有2个连接和2个条件)。

The best performance I managed to achieve was with a compiledquery looking like this 我设法实现的最佳性能是使用看起来像这样的编译查询

Func<MyContext, int, string, IQueryable<RowExtra>> query = 
CompiledQuery.Compile( 
  (MyContext ctx, int position, string orderNumber) => 
    from extra in ctx.RowExtras 
    where 
      extra.Position == position && 
      extra.OrderRow.Order == orderNumber 
    select extra);

and then invoking said query for each object in my list. 然后为列表中的每个对象调用所述查询。 But even this approach took way over a minute. 但即便采用这种方法也需要一分钟。 So how do I actually get this thing to run within a reasonable timeframe? 那么我如何在合理的时间范围内实现这一目标呢?

Also, I'm sorry for the overly long explanation, but hopefully someone can help me! 此外,我很抱歉这个过长的解释,但希望有人可以帮助我!

Try to minimise the number of database calls. 尽量减少数据库调用的次数。 As a rule of thumb, each one will take roughly 10ms at least - even one that just returns a scalar. 根据经验,每个人至少需要大约10毫秒 - 即使只返回一个标量。

So, in general, fetch all the data you will need in one go, modify it in code and then save it. 因此,通常,一次性获取您需要的所有数据,在代码中修改它然后保存它。

List<Order> orders = myContext.Orders
    .Include( "OrderRows.RowExtras" )
    .Where( ... select all the orders you want, not just one at a time ... )
    .ToList();

foreach ( Order order in orders )
{
    ... execute your logic on the in-memory model
}

myContext.SaveChanges();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM