LINQ To Sql Запрос в C# - Любая экспертиза, пожалуйста? Я до сих пор борюсь с этим - PullRequest
2 голосов
/ 18 марта 2020

Я новичок ie в C# / запрос LINQ - у меня запрос ниже (Правильное внешнее объединение прекрасно работает в Simple SQL, однако я не могу реализовать это в LINQ, провел 3 дня в пробной версии) и ошибка, но никуда не денется - какая-либо подсказка, пожалуйста?

SELECT bt.PosGUID,s.PosGUID
    FROM tblSchedule s right Join tblTrade bt
        ON s.PosGUID = bt.PosGUID  AND  RowType = '4'

SELECT bt.PosGUID,s.PosGUID
    FROM  tblTrade bt left Join tblSchedule s 
        ON s.PosGUID = bt.PosGUID  AND  RowType = '4'

Нужно понять, каков наилучший путь к указанному выше левому внешнему соединению, я думаю, что правое внешнее соединение невозможно, поэтому преобразовано в левое соединение и пытается реализовать.

Что-то вроде - кажется, немного сложный запрос:

        var tQuery = from bt in m_DataContext.tblTrades
                     join bPos in m_DataContext.tblBigPositionStatics on
                         new { bt.PosGUID } equals
                         new { bPos.PosGUID }

                     join bo in m_DataContext.tblBigOrders
                         on new { bt.ClOrdID, bt.PosGUID } equals new { bo.ClOrdID, bo.PosGUID }

                     join tradingAcc in m_DataContext.tblTradingAccounts
                         on new { Entity = bPos.PosEntity, Account = bPos.PosAccount } equals
                         new { tradingAcc.Entity, tradingAcc.Account }

                     join btRef in m_DataContext.tblTrades.DefaultIfEmpty()
                         on new { bt.PosGUID, ExecID = bt.ExecRefID } equals new { btRef.PosGUID, btRef.ExecID }
                         into temp
                     from btref in temp.DefaultIfEmpty()

                     join desk in m_DataContext.tblDesks
                     on bt.PosDeskGUID equals desk.GUID

                      // JOIN not working not briging back all records from  TBLTrades
                     join ss in m_DataContext.tblSchedules on bt.PosGUID equals ss.PosGUID into temp1
                     from ss in temp1.DefaultIfEmpty()


                     where bt.CreateDateTime >= dateToRun.getDate(false)
                     && bt.CreateDateTime < dateToRun.getDate(false).AddDays(1)
                     && bo.AsOfDateTime.Date == bt.AsOfDateTime.Date
                     && bPos.HardDeleteDate == null
                      && ss.RowType == "4"


                     //&& !"1".Equals(bt.ExecTransType)
                     //&& bt.HasBeenCorrected == false
                     && deskGuidList.Contains(desk.GUID)


                     select new { bt, bo, desk, bPos, tradingAcc, btref,ss };

1 Ответ

2 голосов
/ 19 марта 2020

Если вы хотите выполнить правое внешнее объединение таблиц A и B, просто замените эти таблицы, и вы можете выполнить левое внешнее объединение.

Левое внешнее объединение - это GroupJoin, за которым следует SelectMany. По своему опыту я использую GroupJoin гораздо чаще, чем левое внешнее соединение. Особенно в отношениях «один ко многим».

Например: Предположим, у вас есть таблица школ и таблица студентов. В каждой школе учится ноль или более учеников, каждый ученик учится ровно в одной школе с использованием внешнего ключа SchoolId: прямое отношение «один ко многим».

Дайте мне все школы со всеми своими учениками

var result = dbContext.Schools
    .GroupJoin(dbContext.Students,          // GroupJoin Schools and Students
    school => school.Id,                    // from every School take the primary key
    student => student.SchoolId,            // from every Student take the foreign key
    (school, studentsOnThisSchool) => new   // from every School with all its Students
    {                                       // make one new object

        // Select only the School properties I plan to use
        Id = schoolId,
        Name = school.Name,

        OlderStudents = studentsOnThisSchool

            .Select(student => new
            {
                // Select only the Student properties I plan to use:
                Id = student.Id,
                Name = student.Name,
                ...

                // not needed, I already know the value:
                // SchoolId = student.SchoolId,
            });

Результатом будет следующая последовательность:

School 1 with Students A, B, C, D.
School 2 with Students E, F,
School 3 without any Students
School 4 with Students G, H, I,
...

Это кажется мне гораздо более полезным, чем результат левого внешнего соединения:

School 1 with Student A,
School 2 with Student E,
School 3 with Null student,
School 1 with Student B,
School 2 with Student F,
School 1 with Student C,
...

Но, эй, это ваш выбор.

У меня есть TblTrade, в котором содержатся сделки. Каждая сделка имеет как минимум свойства Bt, PosGuid и RowType. У меня также есть TblSechedule, который содержит расписания. Каждое расписание имеет как минимум свойства Bt и PosGuid. Дайте мне все сделки с RowType 4 со всеми нулями или более графиками, которые имеют одинаковое значение для PosGuid.

var result = tblTrade
    // keep only the trades that have RowType equal to 4:
    .Where(trade => trade.RowType == 4)

    // do the GroupJoin:
    .GroupJoin(tblSchedule,
         trade => trade.PosGuid,
         schedule => schedule.PosGuid,
         (trade, schedulesWithSamePosGuid) => new
         {
             // Select the trade properties you plan to use:
             TradeId = trade.Id,
             PosGuid = trade.PosGuid,
             ...

             Schedules = schedulesWithSamePosGuid.Select(schedule => new
             {
                  // Select the schedule properties you plan to use:
                  Id = schedule.Id,
                  ...

                  // not needed, you already know the value:
                  // PosGuid = schedule.PosGuid.
              })
              .ToList(),
         });

Если вы действительно хотите плоское внешнее левое соединение, добавьте SelectMany:

.SelectMany(groupJoinResult.Schedules,
(trade, schedule) => new
{
    PosGuid = trade.PosGuid,

    // the Trade properties:
    Trade = new
    {
        Id = trade.TradeId,
        ...
    },

    Schedule = new
    {
        Id = schedule.Id,
        ...
    },
});

Если хотите, вы можете создать функцию расширения LeftOuterJoin:

public static class MyQueryableExtensions
{
    // version without EqualityComparer:
    public static IQueryable<TResult> LeftOuterJoin<T1, T2, TKey, TResult>(
       this IQueryable<T1> source1,
       IQueryable<T2> source2,
       Func<T1, TKey> key1Selector,
       Func<T2, TKey> key2Selector,
       Func<T1, T2, TResult) resultSelector)
    {
        return LeftOuterJoin(source1, source2,
            key1Selector, key2Selector, resultSelector, null);
    }

версия с EqualityComparer:

public static IQueryable<TResult> LeftOuterJoin<T1, T2, TKey, TResult>(
   this IQueryable<T1> source1,
   IQueryable<T2> source2,
   Func<T1, TKey> key1Selector,
   Func<T2, TKey> key2Selector,
   Func<T1, T2, TResult) resultSelector,
   IEqualityComparer<TKey> comparer)
{
    if (comparer == null) comparer = EqualityComparer<TKey>.Default;

    // GroupJoin followed by SelectMany:
    return GroupJoin(source1, source2, key1Selector, key2Selector,
        (source1Item1, source2ItemsWithSameKey) => new
        {
            Source1Item = source1Item,
            Source2Items = source2ItemsWithSameKey,
        })
        .SelectMany(groupJoinResult => groupJoinResult.Source2Items,
           (groupJoinResult, source2Item) =>
               ResultSelector(groupJoinResult.Source1Item, source2Item));

    }
}

Использование:

var result = tblTrade
    .Where(trade => trade.RowType == 4)
    .LeftOuterJoin(tblSchedule,
    trade => trade.PosGuid,
    schedule => schedule.PosGuid,
    (trade, schedule) => new
    {
       // Select the trade and Schedule properties that you plan to use
       // for example the complete trade and schedule:
       Trade = trade,
       Schedule = schedule,

       // or only some properties:
       CommonPosGuid = trade.PosGuid,
       Trade = new
       {
           Id = trade.Id,
           ...
       }

       Schedule = new
       {
           Id = trade.Id,
           ...
       }
    })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...