我对Entity Framework非常陌生,因此,作为测试,我只是创建了一个SQL Server数据库 - 第一个EF6 Winforms项目(在Visual Studio 2013中)并且没有在Visual中更改任何内容Studio创建了代码,例如Lazy / Optimistic loading等。
现在,我从一个有点大的表中获取该项目的所有数据,例如:以下形式的数据:
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
,另一个用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
现在,这很有效,但是当用户在查询新的开始/结束日期时选择新的Val1
时,它会非常缓慢甚至挂起用户界面。< / p>
我肯定这不是正确的方法,只是想知道做出类似这样的事情的正确方法。
当前环境:
另外,即使提供的源代码是VB,我也同样熟悉VB / C#解决方案。
感谢!!!
答案 0 :(得分:3)
根据您提供的内容,我发现您的EF代码没有任何问题。现在大多数人使用LINQ扩展方法来完成他们需要的东西,因为它不像直接LINQ那样冗长。我确实相信他们最终会被转换为扩展方法。
From record in dbContext.MyTable Select new {record.Start_Date};
dbContext.MyTable.Select(x => new {x.Start_Date});
看看它们如何更短并传达相同的含义?
您选择您感兴趣的字段也是一个非常好的习惯。它将减少发送到服务器的查询的大小,并且还会减少服务器返回的结果。
您正在使用using
语句,以便处理上下文,而不会在未使用时保持连接打开。这很好,但是使用winform应用程序,如果上下文应该在显示的表单的生命周期中存在,那么这是值得商榷的。
使用LINQ创建条件时,实际上是正在构建的SQL语句,但尚未执行任何操作。在您可以访问查询结果之前,您需要实现&#34;实现&#34;结果。要执行此操作,您只需访问查询中的元素即可将其发送到服务器以获取结果。您 使用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来处理。通常,客户端在简化的结果集上处理与服务器相同或更好的处理。