Условное объединение в LINQ - PullRequest
2 голосов
/ 14 октября 2011

Так что у меня небольшая проблема с linq. Я хочу, чтобы соединение было OUTER JOIN или INNER JOIN, в зависимости от того, фильтруются ли значения в таблице

НАРУЖНОЕ СОЕДИНЕНИЕ:

var query = (from tblA in dc.tblA
             join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB
             from tblB in joinedTblB.DefaultIfEmpty()
             select tblA);

ВНУТРЕННЕЕ СОЕДИНЕНИЕ:

var query = (from tblA in dc.tblA
             join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB
             from tblB in joinedTblB
             select tblA);

Я хочу объединить это в одном запросе и, проверив какое-либо условие, выполнить OUTER JOIN или INNER JOIN, что-то вроде этого:

var query = (from tblA in dc.tblA
             join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB
             from tblNEWB in ((checkCondition==false) ? joinedTblB.DefaultIfEmpty() : joinedTblB)
             select new {
                tblA.ValueA,
                tblNEWB.ValueB
             });

Я надеялся, что это сработает, но я получаю сообщение об ошибке "InvalidOperationException: доступ к элементу 'System.String ValueB' из 'tblB' недопустим для типа 'System.Collections.Generic.IEnumerable'1 [tblB]"

Я что-то здесь упускаю?

UPDATE

То, что я хочу, - это внешнее соединение, но linq не произвел запрос, на который я надеялся, когда условия установлены для tlbB. Включение SQL Profiler дает этот запрос:

LEFT OUTER JOIN tblB ON tblA.Ref = tblB.REfA AND tlbB.Key = '100'

Хотя правильный запрос должен быть:

LEFT OUTER JOIN tblB ON tblA.Ref = tblB.RefA
WHERE tblB.Key = '100'

Причиной этого является моя функция GetMyTable, которая устанавливает условие для таблицы в соединении.

Ответы [ 3 ]

1 голос
/ 14 октября 2011

Я хочу объединить это в одном запросе, и, проверив какое-либо условие, выполнить OUTER JOIN или INNER JOIN

Первый шаг к получению того, что вы проситеfor должен признать, что требуются два различных SQL-оператора.LinqToSql не собирается отправлять ваше условие в базу данных, поэтому база данных может выяснить, какой тип соединения должен произойти, основываясь на значении.

Второй шаг - переключиться на синтаксис метода.Этот синтаксис является более составным по условиям.

Третий шаг - отказаться от анонимных типов.Вы должны сделать неприятные вещи, чтобы объявить переменные, которые вам нужны для построения запроса с теми, которые бегают.Просто создайте тип с нужными вам свойствами и используйте его.

public class AandB
{
  public A TheA {get;set;}
  public B TheB {get;set;}
}

IQueryable<A> queryA =  dc.TblA.AsQueryable();

IQueryable<AandB> queryAandB = null;

if (checkCondition)
{
  //inner join
  queryAandB = queryA
    .Join(
      GetMyTable(),
      a => a.Ref, b => b.RefA,
      (a, b) => new AandB() {TheA = a, TheB = b}
    );
}
else
{
  // left join
  queryAandB = queryA
    .GroupJoin(
      GetMyTable(),
      a => a.Ref, b => b.RefA,
      (a, g) => new {a, g}
    )
    .SelectMany(
      x => x.g.DefaultIfEmpty(),
      (x, b) => new AandB(){TheA = x.a, TheB = b}
    );
}

List<AandB> results = queryAandB.ToList();
0 голосов
/ 14 октября 2011

Я не уверен, что это именно то, что вы ищете, но оно должно быть близко.

var query = from rowA in db.tblA
            join rowB in db.tblB on rowA.idB equals rowB.idB into b
            from item in b.DefaultIfEmpty()
            select new
            {
                rowA.ValueA,  
                rowB.ValueB
            };
0 голосов
/ 14 октября 2011

если вам нужно левое соединение, ваш первый запрос должен выполнить работу

        (from tblA in dc.tblA
         join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB
         from tblB in joinedTblB.DefaultIfEmpty()
         select new {tblAField = tblA.F1 , tblBField = tblB == null ? null : tblB.F2);

запрос внутреннего соединения будет выглядеть так

        (from tblA in dc.tblA
         join tblB in GetMyTable() on tblA.Ref equals tblB.RefA 
         select new { A = tblA, B = tblB } );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...