[英]Using LINQ to Entities dynamic JOIN
假設您有一個關鍵字表。 為簡單起見,我們只說它有2個字段,一個ID整數,關鍵字varchar(100)。 查詢輸入多個關鍵字。 例如,查詢“快速的棕色狐狸”。 要求是,我們將記錄所有ID至少包含一次出現的所有三個關鍵字的所有記錄。 此外,使用StartsWith可以部分匹配。 我可以使用PredicateBuilder來構建最終將需要的多個OR子句,但還要過濾這些記錄,我需要為每個關鍵字在同一表上執行JOIN。 我應該注意,Id字段不是唯一的,可以有多個條目。
SQL看起來或多或少像這樣或應該
select k1.Id
from Keywords k1
inner join Keywords k2 on k1.Id = k2.Id
inner join Keywords k3 on k2.Id = k3.Id
where k1.Keyword like @k1
and k2.Keyword like @k2
and k3.Keyword like @k3
我到目前為止擁有的LINQ將是
var predicate = PredicateBuilder.False<Keyword>();
foreach (string term in searchTerms)
{
string temp = term;
predicate = predicate.Or(p => p.Keyword.StartsWith(temp));
}
var keys = Keywords.AsExpandable().Where(predicate).ToList();
這將產生或多或少看起來像的SQL:
SELECT
[Extent1].[Id] AS [Id]
FROM [dbo].[Keywords] AS [Extent1]
WHERE ([Extent1].[Keyword] LIKE @p__linq__1 ESCAPE '~') OR ([Extent1].[Keyword] LIKE @p__linq__2 ESCAPE '~') OR ([Extent1].[Keyword] LIKE @p__linq__3 ESCAPE '~')
為了使用此結果,我將不得不做一個DistinctBy,然后再加入我的結果。 這可能會產生巨大的內存需求,我正在嘗試找到一種解決方案,該解決方案可以滿足我在服務器上的大部分需求。
要改寫您的查詢,您要查找ID值,以便該ID的所有關鍵字組包含您要查找的所有搜索詞。
您可以使用GroupBy
,而不是嘗試使用Join
為ID創建所有關鍵字的組,然后,當您擁有共享ID的所有關鍵字的組時,僅過濾掉該組中的關鍵字就足夠簡單了。包含所有搜索詞。
var query = keywords.GroupBy(keyword => keyword.Id)
.Where(group => searchTerms.All(term =>
group.Any(keyword => keyword.Keyword.StartsWith(term)))
.Select(group => group.Key);
最終,我能夠得到它來生成我想要的SQL。 即使這個問題可能是我獨有的,我仍會發布解決方案。 也許對某人有用。
LINQ
var term = searchTerms[0];
var keys = Keywords.Where (k => k.keyword.StartsWith(term));
for(var i=1; i < searchTerms.Length; i++)
{
var searchTerm = searchTerms[i];
keys =
from k1 in keys
join k2 in Keywords on k1.Id equals k2.Id
where k2.keyword.StartsWith(searchTerm)
select k1;
}
產生的SQL:
-- Region Parameters
DECLARE @p__linq__0 VarChar(1000) = 'the%'
DECLARE @p__linq__1 VarChar(1000) = 'brown%'
DECLARE @p__linq__2 VarChar(1000) = 'fox%'
-- EndRegion
SELECT
[Extent1].[Id] AS [Id]
FROM [dbo].[Keywords] AS [Extent1]
INNER JOIN [dbo].[Keywords] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
INNER JOIN [dbo].[Keywords] AS [Extent3] ON [Extent1].[Id] = [Extent3].[Id]
WHERE ([Extent1].[keyword] LIKE @p__linq__0 ESCAPE '~') AND ([Extent2].[keyword] LIKE @p__linq__1 ESCAPE '~') AND ([Extent3].[keyword] LIKE @p__linq__2 ESCAPE '~')
當然,在開始循環之前,我會進行一些檢查以確保我擁有多個searchTerm。 但是你明白了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.