使用实体框架加载/更新控件缓慢-我做错了吗?

本文关键字:错了 缓慢 控件 实体 框架 加载 更新 | 更新日期: 2023-09-27 18:18:58

我是非常新的实体框架,所以,作为一个测试,我只是创建了一个SQL Server数据库- first EF6 Winforms项目(在Visual Studio 2013),并没有改变任何在Visual Studio创建的代码,如懒惰/乐观加载等。

现在,我从一个比较大的表中获取这个项目的所有数据,例如,数据的形式为:

Var1  | Start_Date |  End_Date  |  .... Other Columns ....
---------------------------------------------------------
Val1  | 1/1/2014   |  1/2/2014  |  ...
Val1  | 1/2/2014   |  1/3/2014  |  ...
Val1  | 1/5/2014   |  1/6/2014  |  ...
Val1  | 1/7/2014   |  1/8/2014  |  ...
Val1  | 1/9/2014   |  1/10/2014 |  ...
    ....
Val2  | 1/1/2014   |  1/2/2014  |  ...
Val2  | 3/2/2014   |  3/3/2014  |  ...
    ....

所以,我想要在我的表单上有3个ComboBoxes -一个用户选择Val1,另外2个在ComboBox1.Change上更新,以显示Val1特定值可用的所有唯一的开始和结束日期。

我使用的代码是:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Using ctx As New MyEntities
            Dim Var1Query = (From rw In ctx.MyTable
                             Order By rw.Val1
                             Select rw.Val1).Distinct.ToList
            cboVal1.DataSource = Var1Query 
    End Using
End Sub
Private Sub cboVal1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboVal1.SelectedIndexChanged
    Using ctx As New MyEntities
         ' Figured to get both dates at once rather than 2 trips to the DB
         Dim Dates = (From rw In ctx.MyTable
                      Where rw.Val1= cboVal1.Text
                      Select New With
                      {
                        .Start_Date = rw.Start_Date,
                        .End_Date = rw.End_Date
                      }).ToList

         Dim Start_Dates As List(Of Date)
         Start_Dates = (From el In Dates
                        Select el.Start_Date).Distinct.ToList
         Dim End_Dates As List(Of Date) = 
         End_Dates = (From el In Dates
                      Select el.End_Date).Distinct.ToList
         cboStartDates.DataSource = Start_Dates
         cboEndDates.DataSource = End_Dates
     End Using
End Sub

现在,这工作,但它是非常慢的,甚至挂起UI的时刻,用户选择一个新的Val1,而它正在查询新的开始/结束日期。

确定这不是正确的方法,我只是想知道这样做的正确方法是什么

当前环境:

  • Visual Studio 2013
  • 实体框架6
  • SQL Server 2008

此外,尽管提供的源代码是用VB编写的,但我对VB/c#解决方案同样感到满意。

谢谢! !

使用实体框架加载/更新控件缓慢-我做错了吗?

从您提供的内容来看,我没有看到您的EF代码有任何问题。现在大多数人使用LINQ扩展方法来完成他们需要的东西,因为它不像直接LINQ那样冗长。我相信它们最终会被翻译成扩展方法。

LINQ:

From record in dbContext.MyTable Select new {record.Start_Date};

LINQ扩展:

dbContext.MyTable.Select(x => new {x.Start_Date});

看到它们是如何更短,传达同样的意思吗?

选择你感兴趣的领域也是一个很好的习惯。它将减少发送到服务器的查询的大小,也将减少服务器返回的结果。

您正在使用using语句,因此上下文被处理,而不是在不使用时留下打开的连接。这很好,但是对于winform应用程序,上下文是否应该在显示的表单的生命周期中存在是有争议的。


EF一般

当您使用LINQ创建条件时,这实际上是一个正在构建的SQL语句,但还没有执行任何操作。在访问查询结果之前,需要"具体化"。结果。为此,您只需要访问查询中的一个元素,将其发送到服务器以获取结果。通过使用ToList可以做到这一点。除非您仍然有条件地构建查询,否则您应该始终这样做。

很重要的一点是,在大多数情况下,延迟加载并不是一件好事。它非常方便,但它可以创建n+1个条件,并且您将受到性能影响,因为您在父上访问的每个子集合项都会生成一个查询来获取它。这就是使用AutoMapper之类的工具或使用Include语句将一次从服务器获取所有内容的地方。

例如:var orderWithDetails = db.Orders.Include(order => order.LineItems).FirstOrDefault(order => order.Id == 4);将生成一条SQL语句,它将选择具有id = 4的订单,并生成额外的SQL来选择与它相关的所有LineItem记录。如果你不这样做,并启用了延迟加载,这可能会产生多个子查询,影响性能。

重要的是要记住,ORM只是使我们更容易访问数据,并没有消除对系统其他组件进行性能测试的需要。


编辑:

我觉得这是应该包含的东西,@BrunoMonteiro也指出了这一点。当你选择不同的日期时,你是在一个物化查询Dates上做的。因此,所有这些都将发生在客户端,而不是在SQL Server。这取决于有多少记录与从Where子句返回的记录集相关联,这可能是一个问题。

您应该看到返回了多少和潜在的最大返回值。如果看起来过多,我建议您为它们生成单独的语句,并将它们发送给SQL Server来处理。一般来说,在简化的结果集上,客户机的处理速度与服务器相同,甚至更好。