这个问题根本没有时间执行,但如果我取消注释最后一行需要5秒钟。这怎么会影响查询那么多?这几乎是完全相同的查询。
return db.Parties.Where(predicate).Select(p => new SearchResult
{
adressPerson = p.Contacts.SingleOrDefault(m => m.contact_type == "H").streetname,
//adressOrg = p.Contacts.SingleOrDefault(m => m.contact_type == "W").streetname
});
如何找到问题?
这是谓词的样子:
predicate = predicate.Or(p => p.surname.EndsWith(keyword));
predicate = predicate.Or(p => p.lastname.EndsWith(keyword));
predicate = predicate.Or(p => p.organisation.EndsWith(keyword));
predicate = predicate.Or(p => p.Contacts.Any(c => c.streetname.EndsWith(keyword)));
predicate = predicate.Or(p => p.Memberships.Any(m => m.Congregation.congregation_name.EndsWith(keyword)));
predicate = predicate.Or(p => p.PartyCategories.Any(m => m.Category.category_name.EndsWith(keyword) || m.Category.category_code.EndsWith(keyword)));
我知道发布大量代码是愚蠢的,但无论如何这里都是SQL查询。有线索吗?
SELECT (
SELECT [t6].[streetname]
FROM [dbo].[Contact] AS [t6]
WHERE ([t6].[contact_type] = @p7) AND ([t6].[party_id] = [t0].[party_id])
) AS [adressPerson], (
//SELECT [t7].[streetname]
//FROM [dbo].[Contact] AS [t7]
//WHERE ([t7].[contact_type] = @p8) AND ([t7].[party_id] = [t0].[party_id])
//) AS [adressOrg]
FROM [dbo].[Party] AS [t0]
WHERE ([t0].[surname] LIKE @p0) OR ([t0].[lastname] LIKE @p1) OR ([t0].[organisation] LIKE @p2) OR (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[Contact] AS [t1]
WHERE ([t1].[streetname] LIKE @p3) AND ([t1].[party_id] = [t0].[party_id])
)) OR (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[Membership] AS [t2]
LEFT OUTER JOIN [dbo].[Congregation] AS [t3] ON [t3].[congregation_id] = [t2].[congregation_id]
WHERE ([t3].[congregation_name] LIKE @p4) AND ([t2].[party_id] = [t0].[party_id])
)) OR (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[PartyCategories] AS [t4]
INNER JOIN [dbo].[Category] AS [t5] ON [t5].[category_id] = [t4].[category_id]
WHERE (([t5].[category_name] LIKE @p5) OR ([t5].[category_code] LIKE @p6)) AND ([t4].[party_id] = [t0].[party_id])
))
解决 原来,最后一个select语句中的INNER JOIN不起作用。所以我将谓词的最后一行更改为:
predicate = predicate.Or(p => p.PartyCategories
.GroupJoin(db.Categories, b => b.category_id, c => c.category_id, (b, c) => new { b, c })
.SelectMany(c => c.c.DefaultIfEmpty(), (c, b) => new { c.c, b })
.Any(m => m.b.category_name.EndsWith(keyword) || m.b.category_code.EndsWith(keyword)));
答案 0 :(得分:2)
如何找到问题?
与往常一样,找出方法是查看生成的SQL,并通过SQL事件探查器运行它。
我的猜测是,当你只对单一联系人类型感兴趣时,它会从简单的内部联接变为更复杂的,甚至可能是“N + 1选择”问题。无论如何,查看SQL应该会让它更加清晰。
答案 1 :(得分:0)
尼古拉斯,
我会按照建议查看SQL,看看该级别发生了什么。我还建议在初始linq查询上执行.Include()
,因为这会急切地加载Contacts, Memberships and PartyCategories
个实体。否则,你绝对会在N + 1选择模式上延迟加载。请查看以下链接:.included usage:
http://blogs.msdn.com/b/alexj/archive/2009/06/02/tip-22-how-to-make-include-really-include.aspx
Linq-to-entities - Include() method not loading
http://www.singingeels.com/Articles/Entity_Framework_and_Lazy_Loading.aspx
...欢呼声