2013-02-06 38 views
4

我怎樣才能改變這種查詢LINQ的C#代碼,所有的記錄:SQL到LINQ拿到賽的所有值

SELECT k1.Ad_Id FROM KeywordAdCategories k1, KeywordAdCategories k2 
WHERE k1.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'ALFA') 
AND k2.Keyword_Id = (SELECT Id FROM keywords WHERE name = '145') 
AND k1.Ad_Id = k2.Ad_Id 

的IDEIA是建立基於在可以是N關鍵字的數量動態查詢(在例子中它們是2:ALFA和145)

由於

編輯:

KeywordAdCategory型號:

public class KeywordAdCategory 
{ 
    [Key] 
    [Column("Keyword_Id", Order = 0)] 
    public int Keyword_Id { get; set; } 

    [Key] 
    [Column("Ad_Id", Order = 1)] 
    public int Ad_Id { get; set; } 

    [Key] 
    [Column("Category_Id", Order = 2)] 
    public int Category_Id { get; set; } 
} 

關鍵字型號:

public class Keyword 
{ 
    // Primary properties 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

如果我有5個關鍵詞,我會得到:

SELECT k1.Ad_Id FROM KeywordAdCategories k1, KeywordAdCategories k2, KeywordAdCategories k3, KeywordAdCategories k4, KeywordAdCategories k5 
WHERE k1.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD1') 
AND k2.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD2') 
AND k1.Ad_Id = k2.Ad_Id 
AND k3.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD3') 
AND k2.Ad_Id = k3.Ad_Id 
AND k4.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD4') 
AND k3.Ad_Id = k4.Ad_Id 
AND k5.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD5') 
AND k4.Ad_Id = k5.Ad_Id 
+0

你的C#類是什麼樣的?另外,如果關鍵字的數量是5,你能給出一個SQL的例子嗎?我不明白爲什麼KeywordAdCategories表格會被使用兩次......可能有更好的方法來編寫這個SQL,這將導致更好的LINQ示例。 – Peter

+0

@ɹǝʇǝd我認爲SQL也可以改寫得更好。然而,這個SO問題指出,「更清潔」的解決方案性能較差:http://stackoverflow.com/questions/1054299/sql-many-to-many-table-and-query –

+0

@Peter我只是編輯問題與更多信息 – Patrick

回答

-1
public static int GetAdId(string KeywordId) 
{ 
    var dbContext = new MyDbContext(); 

    var result = (from k in in dbContext.KeywordAdCategories 
        where k.Keyword_Id == KeywordId 
        select k.Ad_Id).SingleOrDefault(); 

    return result; 
} 

運行的所有關鍵字,通過這種方法,IDS,你會得到相應的廣告ID 。我建議你閱讀LINQ。一旦你瞭解它,它是一個很棒的工具,雖然它起初看起來有點可怕,但這並不難學。 Pluralsight.com有很多是很容易掌握,並從:)

+0

反對票是什麼? – Maritim

+0

這不考慮'AND'。這將更像是一個'或' –

+1

如果真的把它放在評論中,而不是簡單地回答一個答案,那將是更有建設性的。 – Maritim

0
List<string> keywordnames = new List<string>(); 
// populate keywordsnames list  

IQueryable<int> AdIds = from k in KeywordAdCategories 
    where 
     (from kw in Keywords where keywordnames.Contains(kw.name) select kw.id) 
     .Contains(k.keyword_id) 
    select k.Ad_Id; 

List<string> keywordnames = new List<string>(); 
// populate keywordsnames list 

List<int> keywordnameids = (from kw in ctx.Keywords 
          where keywordnames.Contains(kw.name) 
          select kw.id).ToList(); 

List<int> AdIds = (from k in ctx.KeywordAdCategories 
        where keywordnameids.Contains(k.Keyword_Id) 
        select k.Ad_Id).ToList(); 
+0

謝謝,但您的答案是返回僅包含關鍵字之一的Ad_Id,並且目標是獲取包含所有關鍵字的Ad_Id – Patrick

+0

@Patrick,仔細檢查關鍵字名稱是否正在填充您正在查找的所有名稱以及在進行字符串比較時考慮到區分大小寫。另外,請嘗試我最近編輯中的第二個示例。 – pwnyexpress

+0

我做了,但即使是第二個例子仍然返回所有具有一個關鍵字或訂單的廣告,而不是兩個 – Patrick

1

學習這是相當有一點麻煩,我想,當第一次看它的偉大的影片,所以我可能過度思考它。但這裏有一個解決方案,我相信會爲你工作:

var keywordList = new List<string>(); 
keywordList.Add("ALFA"); 
keywordList.Add("145"); 

var results = KeywordAdCategories.Select (kac => kac.Ad_Id).Distinct() 
      .Select (a => 
       new 
       { 
        AdId=a, 
        Keywords=KeywordAdCategories.Where(kac => kac.Ad_Id == a).Select(kac => kac.Keyword_Id) 
       }) 
      .Where(ac => ac.Keywords.Intersect(Keywords.Where(kw => keywordList.Contains(kw.Name)).Select (kw => kw.Id)).Count() == keywordList.Count()) 
      .Select (ac => ac.AdId); 

現在來解釋我在這裏做了什麼。首先,我想,所以我們這一行,開始與所有可能的廣告的ID:

KeywordAdCategories.Select (kac => kac.Ad_Id).Distinct() 

當然,這也許可以更容易地從一個不同的選擇取回從廣告表格,但我想唯一的工作與你所定義的。

接下來,我選擇的關鍵字及其相關集合中的每個廣告ID爲匿名列表類型的對象:

.Select (a => 
       new 
       { 
        AdId=a, 
        Keywords=KeywordAdCategories.Where(kac => kac.Ad_Id == a).Select(kac => kac.Keyword_Id) 
       }) 

接下來,我篩選結果只包含關鍵詞的集合,與相交的對象我們關鍵字列表,並具有與我們的關鍵字列表相同數量的結果元素。

.Where(ac => ac.Keywords.Intersect(Keywords.Where(kw => keywordList.Contains(kw.Name)).Select (kw => kw.Id)).Count() == keywordList.Count()) 

,最後我選擇了剛剛的廣告ID所導致

.Select (ac => ac.AdId); 

這裏是emmited SQL如果您位數的

-- Region Parameters 
DECLARE @p0 NVarChar(1000) = 'ALFA' 
DECLARE @p1 NVarChar(1000) = '145' 
DECLARE @p2 Int = 2 
-- EndRegion 
SELECT [t1].[Ad_Id] 
FROM (
    SELECT DISTINCT [t0].[Ad_Id] 
    FROM [KeywordAdCategories] AS [t0] 
    ) AS [t1] 
WHERE ((
    SELECT COUNT(*) 
    FROM (
     SELECT DISTINCT [t2].[Keyword_Id] 
     FROM [KeywordAdCategories] AS [t2] 
     WHERE (EXISTS(
      SELECT NULL AS [EMPTY] 
      FROM [Keywords] AS [t3] 
      WHERE ([t2].[Keyword_Id] = [t3].[Id]) AND ([t3].[Name] IN (@p0, @p1)) 
      )) AND ([t2].[Ad_Id] = [t1].[Ad_Id]) 
     ) AS [t4] 
    )) = @p2 

我相信有更優雅方法來完成你想要做的事情,但我想看看是否可以在一個linq查詢中完成所有事情。希望這可以幫助。

+0

嗨,謝謝!它正在工作!任何機會,你可以合併此代碼與這一個:http://stackoverflow.com/questions/14324390/? – Patrick