2015-06-26 21 views
1

加入列表,我有一個列表:LINQ的異常,當一個查詢結果

List<MyClass> lstClass1; 

如果MyClass的有2個簡單的字符串屬性:

class MyClass 
{ 
    public string property1 { get; set; } 
    public string property2 { get; set; } 
} 

而且我對DB,MyTable的表,至查詢,其中有兩個字符串類型的列:

MyTable 
    column MainKey 
    column AlternativeKey 

對於我的劇本,我必須選擇加入DB和名單,與弗洛wing規則:如果AlternativeKey存在,如果AlternativeKey中的前4個字符等於MyClass.property1或MyClass.Property2,則選擇該行;否則,如果MainKey中的前4個字符等於MyClass.property1或MyClass.Property2,則選擇該行。這是我的實現:

IQueryable<MyTable> source = getMyTable(); 
List<MyClass> lstClass1 = getListClass(); 

IQueryable<MyClass> qMyClassList = lstClass1.AsQueryable<MyClass>(); 

IQueryable<MyTable> selAlternative = from alt in source 
            join cl1 in qMyClassList on 
            alt.AlternativeKey.Substring(0, 4) 
            equals cl1.property1 
            join cl2 in qMyClassList on 
            alt.AlternativeKey.Substring(0, 4) 
            equals cl2.property2 
            where alt.AlternativeKey != null && alt.AlternativeKey.Length >= 4 
            select alt; 

IQueryable<MyTable> selMain = from main in source 
            join cl1 in qMyClassList on 
            main.MainKey.Substring(0, 4) 
            equals cl1.property1 
            join cl2 in qMyClassList on 
            main.MainKey.Substring(0, 4) 
            equals cl2.property2 
            where main.AlternativeKey == null && main.MainKey.Length >= 4 
            select main; 

source = alt.Union(main); 

在執行中,這個查詢提出這個異常,當我循環的結果元素:

無法創建類型爲「MyTable的+ MyClass的」一個恆定值。在此上下文中僅支持 基元類型或枚舉類型。

我做錯了什麼?

+0

請勿在查詢中使用相等運算符(「==」)。 –

回答

1

您正在加入內存集合:qMyClassListIQueryable數據源。例外是因爲IQueryable LINQ提供程序無法將join轉換爲相關查詢。

2個選項,你可以考慮:

選項1:你可以嘗試在where,而不是使用joinContains。您的LINQ查詢提供程序可能會將您的查詢解釋爲WHERE .. IN ('val1','val2'...)。因此,對於你,這將是這個樣子:

var selAlternative = from alt in source 
        where alt.AlternativeKey != null && 
          property1List.Contains(alt.AlternativeKey.Substring(0, 4)) && 
          property2List.Contains(alt.AlternativeKey.Substring(0, 4)) && 
        select alt; 

記住Contains將只與原始類型的工作。在你的情況下,這似乎是string,所以沒關係。

選項2,如果您想保持您的連接狀態,只需.ToList()您的source實例。這通常不是一個好主意,如果你的來源是大的,因爲你的整個數據集加載到內存中並加入存儲應用):

var selAlternative = from alt in source.ToList() 
        join cl1 in qMyClassList on ... 
+0

如果'MyClass'列表已經在內存中,我懷疑刪除了'.AsQueryable ()'清除了這個問題。 (編輯:好吧,_and_不會將其聲明爲可查詢) – clarkitect

0

尼爾斯,選項1是一個很好的建議,但我必須像這樣過濾:

IQueryable<MyTable> source = getMyTable(); 
List<MyClass> lstClass1 = getListClass(); 

var property1List = (from prp in lstClass1 select prp.property1).Distinct(); 
var property2List = (from prp in lstClass1 select prp.property2).Distinct(); 

var selAlternative = from alt in source 
        where alt.AlternativeKey != null && 
        (property1List.Contains(alt.AlternativeKey.Substring(0, 4)) || 
        property2List.Contains(alt.AlternativeKey.Substring(0, 4))) 
        select alt; 

var selMain = from main in source 
        where main.AlternativeKey == null && 
        (property1List.Contains(main.MainKey.Substring(0, 4)) || 
        property2List.Contains(main.MainKey.Substring(0, 4))) 
        select main; 

source = alt.Union(main); 

謝謝!

+1

請注意,兩個'Contains' [與一個連接不同](http://stackoverflow.com/a/26201371/861716)! –