使用实体框架加载/更新控件缓慢-我做错了吗?
本文关键字:错了 缓慢 控件 实体 框架 加载 更新 | 更新日期: 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来处理。一般来说,在简化的结果集上,客户机的处理速度与服务器相同,甚至更好。