2011-03-09 25 views
3

我試圖減少數據庫查詢的次數,並且在做這件事情時我試圖一次性檢索一系列分層實體(以前是遞歸提取的)。Linq的靜態函數'Contain'在嵌套查詢中搞亂了它的內容?

我有一個Labels持有物業一組字符串:

public string[] Labels { get; set; } // new string[] {"{{a}}", "{{b}}", "{{c}}", "{{d}}", "{{e}}"}; 

,我使用構造一個第一查詢:

var IDeferredTopLabels= 
    db.labels 
     .Where(l => 
      l.site_id == this.site_id && 
      this.Labels.Contains(l.name_for_code) 
     ) 
    .Select(l => new LabelWithParentId { Label = l, ParentId = null }); 

以上,如果檢查在調試時,會生成以下TSQL

SELECT [t0].[id], [t0].[name_for_code], [t0].[site_id], [t0].[priority_level] 
FROM [dbo].[labels] AS [t0] 
WHERE ([t0].[site_id] = 15) AND ([t0].[name_for_code] IN ('{{a}}', '{{b}}', '{{c}}', '{{d}}', '{{e}}')) 

到目前爲止好,繼IDeferredToplabels聲明我伸出了Union第一查詢指定孩子Label實體應如何獲取:

var IDeferredWithChildLabels = IDeferredTopLabels 
    .Union(
     db.label__labels 
     .Where(ll => 
      db.labels 
       .Where(l => 
        l.site_id == this.site_id && 
        this.Labels.Contains(l.name_for_code) 
       ) 
      .Select(l => l.id) 
      .Contains(ll.parent_label_id) 
     ) 
    .Select(ll => new LabelWithParentId { Label = ll.label1, ParentId = ll.parent_label_id}) 
    ); 

現在,如果我檢查TSQL產生是:

SELECT [t4].[id], [t4].[name_for_code], [t4].[site_id], [t4].[priority_level], [t4].[value] AS [ParentId] 
FROM (
    SELECT [t0].[id], [t0].[name_for_code], [t0].[site_id], [t0].[priority_level], NULL AS [value] 
    FROM [dbo].[labels] AS [t0] 
    WHERE ([t0].[site_id] = 15) AND ([t0].[name_for_code] IN ('{{a}}', '{{b}}', '{{c}}', '{{d}}', '{{e}}')) 
    UNION 
    SELECT [t2].[id], [t2].[name_for_code], [t2].[site_id], [t2].[priority_level], [t1].[parent_label_id] AS [value] 
    FROM [dbo].[label__label] AS [t1] 
    INNER JOIN [dbo].[labels] AS [t2] ON [t2].[id] = [t1].[label_id] 
    WHERE EXISTS(
     SELECT NULL AS [EMPTY] 
     FROM [dbo].[labels] AS [t3] 
     WHERE ([t3].[id] = [t1].[parent_label_id]) AND ([t3].[site_id] = 15) AND ([t3].[name_for_code] IN ('{{a}}', '{{b}}', '{{c}}', '{{a}}'0, '{{a}}'1)) 
     ) 
    ) AS [t4] 

如果你在看到底在第二個TSQL查詢中,部分IN ('{{a}}', '{{b}}', '{{c}}', '{{a}}'0, '{{a}}'1)),字符串集合中第二個倒數第二個倒數第二個元素加上它不再是初始字符串集合(即'{{a}}','{ {b}}','{{c}}','{{d}}',{{e}}'),而不是'{{a}}', '{{b}}', '{{c}}', '{{a}}', '{{a}}'

我在做什麼錯了!?

我很笨,我感謝你的幫助,謝謝。

編輯:

我只是試圖使用int[]和比較id甚則name_for_code,我仍然得到1和0附加到該陣列的最後2種元素以及陣列元件是錯誤:

SELECT [t4].[id], [t4].[name_for_code], [t4].[site_id], [t4].[priority_level], [t4].[value] AS [ParentId] 
FROM (
    SELECT [t0].[id], [t0].[name_for_code], [t0].[site_id], [t0].[priority_level], NULL AS [value] 
    FROM [dbo].[labels] AS [t0] 
    WHERE ([t0].[site_id] = 15) AND ([t0].[id] IN (1, 2, 3, 4, 5)) 
    UNION 
    SELECT [t2].[id], [t2].[name_for_code], [t2].[site_id], [t2].[priority_level], [t1].[parent_label_id] AS [value] 
    FROM [dbo].[label__label] AS [t1] 
    INNER JOIN [dbo].[labels] AS [t2] ON [t2].[id] = [t1].[label_id] 
    WHERE EXISTS(
     SELECT NULL AS [EMPTY] 
     FROM [dbo].[labels] AS [t3] 
     WHERE ([t3].[id] = [t1].[parent_label_id]) AND ([t3].[site_id] = 15) AND ([t3].[id] IN (1, 2, 3, 10, 11)) 
     ) 
    ) AS [t4] 
+0

如果涉及的字面串是'a b c d e'(即沒有'{{}}'),你還會得到這種行爲嗎? – AakashM 2011-03-09 15:26:08

+1

我無法做出正面或反面的這 - 爲什麼你的SQL參數化? LinqToSql將生成參數化查詢。 – 2011-03-09 16:03:04

+0

@AakashM:我嘗試刪除'{{}}}'但我仍然得到'IN''''''''''')' – 2011-03-09 17:07:12

回答

2

OK我發現這個問題,實際上僅在調試模式下運行的代碼時,但具體現在看來,這是斯科特谷的一個錯誤是沒有發生LINQ to SQL Debug Visualizer

這就是爲什麼我被抓住了TSQL是沒有參數化,@David B你提出了一個很好的觀點!

我會留下評論斯科特顧的頁面指向這個問題。

謝謝大家!

0

嘗試複製Labels並在查詢的第二部分(聯盟)中使用它。 EG:

string[] LabelsCopy = new string[5]; 
Labels.CopyTo(LabelsCopy, 0); 

然後設置查詢後一個斷點和檢查每個陣列的內容(或打印出兩個陣列中的內容與Console.WriteLine(String.Join(',',Labels)))。

.Contains()改變Labels的內容是極不可能的,但如果是這樣的話,那麼你就會有證據。

+0

我試過了,它沒有任何區別。但是,如果我檢查this.Labels或LabelsCopy,它們都具有正確的值,在定義IDeferredWithChildLabels之前和之後。 – 2011-03-09 17:04:00