这两个查询之间有什么区别?
它们不是一样的,哪一个是快速的?在哪里使用后会出现什么问题?写在哪里之后使我的代码对我来说可读。我做错了吗?
首先查询:
Model= (model.Where(p => p.Date.Year == yilim)
.Where(p => p.Id== 2 || p.Id== 3)
.OrderBy(m => m.Date.Month))
.ToList();
第二次查询:
Model= (model.Where(p => p.Date.Year == yilim && (p.Id== 2 || p.Id== 3))
.OrderBy(m => m.Date.Month))
.ToList();
答案 0 :(得分:5)
没有功能的区别,因为菊花链Where
调用是一个逻辑AND
操作,您目前正在AND
两个独立的条件一起。
但是,在删除编译器优化条件检查(例如短路)的能力以及第二个(道歉,那部分只适用于Linq to Objects。)Where
所需的额外枚举器方面可能效率稍低只有一个普查员。
如果您的代码符合OR
条件,则只有第二个查询会提供您想要的内容:
Model= (model.Where(p => p.Date.Year == yilim || p.Id== 2 || p.Id== 3)
.OrderBy(m => m.Date.Month))
.ToList();
// Cannot express the above query in simple daisy-chained Where calls.
如果Where
中的逻辑变得难以阅读,请尝试“无评论编码”并将条件填入具有可读名称的方法中,然后您可以执行.Where(x => TheCustomerNameIsValid(x))
或方法分组它.Where(TheCustomerNameIsValid)
(当你可以)。这也有助于调试,因为在一个方法中放置断点比在lambda中放置断点要少一些。
答案 1 :(得分:3)
不同之处在于,在第一个查询中,第一个Where将应用于名为model的序列,并且在结果序列中将应用第二个where方法。而在第二个查询中,Where方法应用于称为模型的序列。话虽如此,第二个查询从第一个查询开始效率更高,因为您只运行一次模型序列。
然而,说明第二个是从理论上更有效的步骤。我不认为在实践中你会得到任何重要的,如果有的话,可衡量的差异。
答案 2 :(得分:2)
您不太可能注意到两者之间存在任何显着的性能差异。两次调用Where()
会增加一些开销:你创建了一个额外的中间对象,当然在枚举期间还有额外的方法调用来处理。
但在大多数代码中,这些差异并不明显。如果通过将过滤器拆分为两个单独的Where()
调用,您发现代码更易于阅读和维护,那么这是更好的方法。
至少,也就是说,直到做出现真正的性能问题。然后你可以回过头来重新审视这是否是你问题的一部分,值得改变。
答案 3 :(得分:2)
其他'答案非常明确,但我得到了不同的建议。为什么不通过调试检查生成的SQL查询。您将看到它们之间是否存在差异。要获取系统生成并运行的实际SQL查询,可以按如下方式编写:
using (EntityConnection con = new EntityConnection("Name = testEntities"))
{
con.Open();
using (testEntities db = new testEntities())
{
int yilim = 2013;
IQueryable<Model> models = (db.Model.Where(p => p.Date.Year == yilim)
.Where(p => p.ID == 2 || p.ID == 3)
.OrderBy(m => m.Date.Month))
.AsQueryable();
string modelsQuery = ((System.Data.Objects.ObjectQuery)models).ToTraceString();
IQueryable<Model> models2 = (db.Model.Where(p => p.Date.Year == yilim &&
(p.ID == 2 || p.ID == 3))
.OrderBy(m => m.Date.Month))
.AsQueryable();
string modelsQuery2 = ((System.Data.Objects.ObjectQuery)models2).ToTraceString();
System.IO.File.WriteAllText(@"C:\Users\username\Desktop\queries.txt",
"Query 1:\r\n" + modelsQuery + "\r\n" +
"Query 2:\r\n" + modelsQuery2);
}
结果是:
Query 1:
SELECT
[Project1].[ID] AS [ID],
[Project1].[Date] AS [Date]
FROM ( SELECT
DATEPART (month, [Extent1].[Date]) AS [C1],
[Extent1].[ID] AS [ID],
[Extent1].[Date] AS [Date]
FROM [dbo].[Model] AS [Extent1]
WHERE ((DATEPART (year, [Extent1].[Date])) = @p__linq__0) AND ([Extent1].[ID] IN (2,3))
) AS [Project1]
ORDER BY [Project1].[C1] ASC
Query 2:
SELECT
[Project1].[ID] AS [ID],
[Project1].[Date] AS [Date]
FROM ( SELECT
DATEPART (month, [Extent1].[Date]) AS [C1],
[Extent1].[ID] AS [ID],
[Extent1].[Date] AS [Date]
FROM [dbo].[Model] AS [Extent1]
WHERE ((DATEPART (year, [Extent1].[Date])) = @p__linq__0) AND ([Extent1].[ID] IN (2,3))
) AS [Project1]
ORDER BY [Project1].[C1] ASC
他们是完全相同的。因此,预计这里的性能不同。
答案 4 :(得分:2)
写在哪里之后使我的代码对我来说可读。我做错了吗?
其他人评论了性能/实际编译的好处,我只是建议代码的可读性(具有宗教性质,所以请使用grain of salt)。
重新格式化第一个查询:
Model= (model.Where(p => p.Date.Year == yilim)
.Where(p => p.Id== 2 || p.Id== 3)
.OrderBy(m => m.Date.Month))
.ToList();
我的偏好是将方法与应用的类对齐。 多维语句可能如下所示:
Model= (model.Where(p => p.Date.Where(d => d.Year == 2014)
.Where(d => d.Month == 11))
.Where(p => p.Id== 2 || p.Id== 3)
.OrderBy(m => m.Date.Month))
.ToList();
重新格式化的第二个查询:
Model= (model.Where(p => p.Date.Year == yilim
&& (p.Id== 2 || p.Id== 3))
.OrderBy(m => m.Date.Month))
.ToList();
为了便于中的操作符,我选择将所有OR内联,并将所有AND保留在不同的行中。
Model = model.Where(m => (m.Name == "jon" || m.Name == "joe")
&& (m.Color == "red" || m.Color == "blue"));
最后,我通常将lambda表达式参数缩短为与变量的第一个字母匹配的字母。
所以:
Model= (model.Where(p => p.Date.Year == yilim)
变为:
Model= (model.Where(m => m.Date.Year == yilim)
对于更复杂的查询,我还使用了:
query = persons.Where(person => person == ...
.Where(person => person.Friends.Where(friend =>
有时单个字母很难与表达式关联,而不必阅读整个表达式树正在做什么。