2016-06-22 58 views
3

我已經創建了基於一個公共列的通用extension方法來加入2 tables。代碼如下:LINQ JOIN使用2列的通用擴展方法

public class SomeDTO<T,U> 
    { 
     public T TableA { get; set; } 
     public U TableB { get; set; } 
    } 
    public static class Helper 
    { 
     public static IQueryable<SomeDTO<T,U>> JoinExtension<T,U,Key>(this IQueryable<T> tableA, IQueryable<U> tableB, Expression<Func<T,Key>> columnA, Expression<Func<U,Key>> columnB) 
     { 
      return tableA.Join(tableB, columnA, columnB,(x, y) => new SomeDTO<T, U>{TableA = x,TableB = y}); 
     } 
    } 

現在在database表有2個共同的列(身份證,輸入),我需要寫一個常見的擴展方法加入基於2個共有列,這些表中,寫的東西如下圖所示:

public static IQueryable<SomeDTO<T, U>> JoinExtensionTwoColumns<T, U, Key>(this IQueryable<T> tableA, IQueryable<U> tableB, Expression<Func<T, Key>> columnA, Expression<Func<U, Key>> columnB, Expression<Func<T, Key>> columnC, Expression<Func<U, Key>> columnD) 
    { 
    return tableA.Join(tableB, a => new { columnA, columnB }, b => new { columnC, columnD }, (a, b) => new SomeDTO<T, U> { TableA = a, TableB = b }); 
    } 

編譯器給我的代碼tableA.Join行規定如下錯誤....如下:

The type arguments for method 'Queryable.Join<TOuter, TInner, TKey, TResult>(IQueryable<TOuter>, IEnumerable<TInner>, Expression<Func<TOuter, TKey>>, Expression<Func<TInner, TKey>>, Expression<Func<TOuter, TInner, TResult>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. 

這是無法理解arguments及其性質正確。

任何指向我可能會出錯的地方?

編輯:

我現在有這編譯成功的方法,但我得到一個運行時錯誤 「The LINQ expression node type 'Lambda' is not supported in LINQ to Entities.

public static IQueryable<SomeDTO<T, U>> JoinExtensionTwoColumns<T, U, Key>(this IQueryable<T> tableA, IQueryable<U> tableB, Expression<Func<T, Key>> columnA, Expression<Func<U, Key>> columnB, Expression<Func<T, Key>> columnC, Expression<Func<U, Key>> columnD) 
     { 
return tableA.Join(tableB, a => new object[]{ columnA, columnB }, b => new object []{ columnC, columnD }, (a, b) => new SomeDTO<T, U> { TableA = a, TableB = b }); 
} 

調用方法,例如:

var result= (db.table1.JoinExtensionTwoColumns<table1,table2,int>(db.table2, c => c.id.ToString(), d => d.id.ToString(),e => e.type, f => f.type)).Take(10); 

任何更多的指針。

+0

你有一個匿名類型,需要一個名稱:new {columnA,columnB}(2個地方)。您也可以使用object:new object [] {columnA,columnB}。任何類型都會自動轉換爲對象,但在將類型對象分配給特定類型時需要進行轉換。 – jdweng

+0

@ jdweng ..我試過你說過的話。儘管沒有編譯器錯誤,但運行時錯誤'LINQ to Entities不支持LINQ表達式節點類型'Lambda''。我正試圖弄清楚。謝謝 – Anurag

+0

@jdweng:請參閱編輯並提供一些指示。謝謝 – Anurag

回答

3

你已經完成了所有的工作:不需要JoinExtensionTwoColumns方法,你可以使用JoinExtension基於幾個列連接表:

tableA.JoinExtension<TypeA, TypeB, object>(tableB, x => new { x.column1, x.column2 }, 
    x => new { column1 = x.column2, column2 = x.column3 }); 

但在這種情況下 - 解不TypeSafely因第三個任意 - object類型參數,要修復它,您可以用這種方法重構以前的解決方案:

public static class Helper 
{ 
    public class JoinCondition<TFirst, TSecond> 
    {    
     public TFirst column1 { get; set; } 
     public TSecond column2 { get; set; } 
    } 

    public static IQueryable<SomeDTO<T, U>> JoinExtension<T, U, TFirst, TSecond>(this IQueryable<T> tableA, IQueryable<U> tableB, 
     Expression<Func<T, JoinCondition<TFirst, TSecond>>> joinSelectorA, 
     Expression<Func<U, JoinCondition<TFirst, TSecond>>> joinSelectorB) 
    { 
     return tableA.Join(tableB, joinSelectorA, joinSelectorB, (x, y) => new SomeDTO<T, U> { TableA = x, TableB = y }); 
    } 
} 

Implementaion:

var answer = context.TableA.JoinExtension(context.TableB, 
    x => new Helper.JoinCondition<int, string> { column1 = x.prop1, column2 = x.prop2}, 
    x => new Helper.JoinCondition<int, string> { column1 = x.prop3, column2 = x.prop4} 
    ).ToList(); 

附: JoinExtensionTwoColumns方法中包含的錯誤:你用 columnA,columnB和等欄目,但他們謂詞,你可以 修復它這樣(它不會在EF上下文工作):

public static IQueryable<SomeDTO<T, U>> JoinExtensionTwoColumns<T, U, Key>(this IQueryable<T> tableA, IQueryable<U> tableB, 
    Expression<Func<T, Key>> columnA, Expression<Func<U, Key>> columnB, 
    Expression<Func<T, Key>> columnC, Expression<Func<U, Key>> columnD) 
{ 
    return tableA.Join(tableB, 
     a => new { column1 = columnA.Compile()(a), column2 = columnC.Compile()(a) }, 
     b => new { column1 = columnB.Compile()(b), column2 = columnD.Compile()(b) }, 
     (a, b) => new SomeDTO<T, U> { TableA = a, TableB = b }); 
} 
+0

@Slava ...謝謝你的回答。讓我試試你的建議。 – Anurag

+0

@Slava ...您對JoinExtensionTwoColumns的編輯會生成一個運行時錯誤,儘管'LINQ表達式節點類型'Invoke'在LINQ to Entities中不受支持。'。關於它的任何想法?同時我正在嘗試你的第一個方法。 – Anurag

+0

發生此錯誤,因爲您可能在EF上下文中執行此查詢。當然,這將會發生,但是你沒有在你的問題中指出這個事實。如果你想在簡單的'List '集合上嘗試這種方法,那麼所有的工作都是可行的。 –