2010-03-11 40 views
4

在我看來,它的問題您是否使用臨時儲存一個IQueryable或不是一個變量給出NotSupportedException異常。參見簡化下面的例子:LINQ到SQL使用本地變量時

這工作:

List<string> jobNames = new List<string> { "ICT" }; 
var ictPeops = from p in dataContext.Persons 
       where ( from j in dataContext.Jobs 
         where jobNames.Contains(j.Name) 
         select j.ID).Contains(p.JobID) 
       select p; 

但是當我使用臨時存儲變量子查詢我得到一個異常:

List<string> jobNames = new List<string> { "ICT" }; 
var jobs = from j in dataContext.Jobs 
      where jobNames.Contains(j.Name) 
      select j.ID; 
var ictPeops = from p in dataContext.Persons 
       where jobs.Contains(p.JobID) 
       select p; 

「System.NotSupportedException:查詢 與當地的集合都不會 支持」

我看不出有什麼問題。這是不是應該在LINQ中工作的邏輯?

UPDATE: 昨天我找到了解決方法,同時使用多個變量來獲得1個查詢:

var jobs = from j in dataContext.Jobs 
      where jobNames.Contains(j.Name) 
      select j.ID; 
    var ictPeops = from p in dataContext.Persons 
       join j in jobs on p.JobID equals j 
       select p; 

但我仍然很困惑。任何人都可以闡明爲什麼第一個查詢在使用變量時不起作用?

+0

我無法重現。請將您的Linq上傳到SQL架構併發送給我們鏈接 – Andrey

回答

3

LINQ-2-SQL將您的代碼轉換爲T-SQL。它可以輕鬆地將您的工作名稱列表作爲參數傳遞。但是,在發生故障的查詢,你試圖加入一個SQL表(人)到C#對象(作業);這是一個複雜的C#類型,不能轉換爲SQL。在第二個查詢中使用它之前,您可能需要將作業轉換爲簡單的int數組。 LINQ-2-SQL可能能夠處理該問題。

+0

我不認爲你理解這個問題。您所指的「複雜」c#類型是一個IQueryable 其中源是相同的數據上下文。當我將它轉換成一個IEnumerable(就像一個數組)時,它會起作用,但linq2sql將執行2個查詢。這不是一個選項。 – nicojs

+0

我認爲生成的異常非常簡潔地描述了問題:「不支持使用本地集合的查詢」。這是LINQ-2-SQL的限制。 –

+0

如果jobNames是一個簡單的數據結構(即List,Array),那麼代碼「where jobNames.Contains(j.Name)」導致SQL看起來像「WHERE Name IN(@ p0,@ p1,...)」 。但既然jobNames是一個IQueryable,L2S不能翻譯這個。你的第三個例子的工作原理是因爲語法不同:「在p.JobID中加入j作業等於j」。 L2S仍然知道'j'是指Jobs表,所以得到的SQL如下所示:「FROM [Persons] AS [t0] INNER JOIN [Jobs] AS [t1] ON [t0]。[JobID] = [t1]。[ID]「 –

-1

讓我解釋的LINQ to SQL是如何工作的。當您在代碼中編寫查詢時,此代碼不會像其他.net代碼和Linq到對象一樣執行。這段代碼然後被分解成表達式樹並編譯成SQL。如果你把所有東西都寫成單個表達式,那麼它將完全轉換爲SQL。當你打破兩個查詢時,它將被分解爲兩個單獨的查詢。 Linq To SQL無法組裝它們。

+0

這是不正確的。由於這兩個查詢都是表達式樹,LINQ to SQL將產生一個SQL語句。這不是問題。 – Steven

+0

「LINQ to SQL將產生一個SQL語句」 - 你能證明這一點嗎? – Andrey

+0

查看我的更新,給出linq查詢生成以下查詢: SELECT [t0]。[ID],[t0]。[Name],[t0]。[JobID] FROM [dbo]。[Person] AS [t0] WHERE [t1]。[Name] IN(@ p0) - @ p0: INNER JOIN [dbo]。[Job] AS [t1] ON [t0]。[JobID] = [t1]。輸入NVarChar(大小= 3; Prec = 0; Scale = 0)[ICT] - 上下文:SqlProvider(Sql2008)模型:AttributedMetaModel構建:3.5.30729.1 – nicojs

0

嘗試轉換VAR jobs到類型的IList

var jobs = (from j in dataContext.Jobs 
      where jobNames.Contains(j.Name) 
      select j.ID).ToList(); 
+0

不,這不是我正在尋找。ToList當然會工作,但會產生2個查詢。在我的業務中,這意味着第二個選擇查詢將有大約30000個輸入參數,這不應該是解決方案。 – nicojs

0

出於好奇,請問這項工作? (我不是一個大的LINQ到SQL的傢伙)

var jobNames = from s in new string[] { "ICT" } 
     select s; 
var jobs = from j in dataContext.Jobs 
     where jobNames.Contains(j.Name) 
     select j.ID; 
var ictPeops = from p in dataContext.Persons 
      where jobs.Contains(p.JobID) 
      select p; 

編輯:好吧,一個大的查詢怎麼樣? :)

var ictPeops = 
    from p in dataContext.Persons 
     let jobs = 
      from j in dataContext.Jobs 
      let jobNames = from s in new string[]{"ICT"} select s 
      where jobNames.Contains(j.Name) 
      select j.ID 
    where jobs.Contains(p.JobID) 
    select p; 
+0

不,同樣的問題。第一部分將工作,因爲jobNames的類型是IEnumerable ,並被視爲與我使用的字符串列表相同。 同樣的問題,如果ictPeops雖然... – nicojs

+0

嗯...好吧,還有一個想法 - 檢查編輯。 – JerKimball

+0

不,你的第二個查詢我得到了同樣着名的System.NotSupportedException。請注意,我的第一個查詢確實有效。 – nicojs