2016-06-22 2 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 общих столбцов (Id, тип), мне нужно написать общий метод расширения, чтобы присоединиться к этим таблицам, основанные на 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 и их характер правильно.

Любые указатели на то, где я, возможно, ошибаюсь?

EDIT:

теперь у меня есть метод, который успешно компилируется, но я получаю сообщение об ошибке выполнения, что "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 места). Вы также можете использовать объект: new object [] {columnA, columnB}. Любой тип будет автоматически добавлен к объекту, но вам нужно передать его при назначении объекта типа конкретному типу. – jdweng

+0

@ jdweng .. Я пробовал то, что вы сказали. Однако ошибка компилятора, но ошибка времени выполнения «Тип узла выражения LINQ« Lambda »не поддерживается в LINQ to Entities. '. Я пытаюсь понять это. Спасибо – 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(); 

P.S. 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 ' коллекциях, все будет работать. –

Смежные вопросы