LINQ LEFT OUTER JOIN, WHERE & MIN / MAX / Подсчет сложности - PullRequest
1 голос
/ 21 мая 2011

Я новичок в LINQ и нахожу это немного сложным для понимания некоторых потоков преобразования данных, так как каждый оператор LINQ связан друг с другом.У меня достаточно стандартный оператор SQL типа, и мне сложно создать подобный оператор LINQ.

Объединение и группировка кажутся довольно простыми, однако, когда я наконец пытаюсь получить SelectЗаявление происходит и положить все различные поля из обеих таблиц, вещи, кажется, распадаются для меня.Я надеюсь, что смогу опубликовать некоторый код SQL, а затем моя попытка связать выражение LINQ вместе с людьми здесь может ответить на мои вопросы о том, КАК это в основном должно работать.Уверен, что LINQ ВСЕ сломан.: - /

У меня есть следующий оператор SQL, который предоставляет мне выбор данных, которые я хотел бы затем использовать и передать элементу управления сеткой.(Однако используя LINQ to Objects)

Вот оператор SQL, который я пытаюсь эмулировать в LINQ:

SELECT s.STRUCTURE_ID, s.TITLE, s.PHOTO, s.PHOTO_LINK, COUNT(s.STRUCTURE_ID)
   AS "How Many Activities", MIN(m.START_DATE) AS "START DATE", MAX(m.FINISH_DATE) AS "FINISH DATE"
FROM DB.STRUCTURES s
LEFT OUTER JOIN DB.ACTIVITIES m ON s.STRUCTURE_ID = m.STRUCTURE_ID
WHERE s.PARK = 'Elwood' AND m.CONTRACT_NO IS NOT NULL
GROUP BY  s.STRUCTURE_ID, s.TITLE, m.STATUS, s.PHOTO, s.PHOTO_LINK
ORDER BY s.STRUCTURE_ID

DB.Structures - это ОДИН файл

DB.Activities - это МНОГО файла

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

Полученные в результате коллекции данных должны быть сведенной коллекцией, которую я могу просто передать своему элементу управления сеткой в ​​следующем формате:

Structure ID     Description           Photo      Start Date     Finish Date
HL-100           Activity Room 100     Yes        6/6/2011       8/26/2011
HS-400A          Small Ones Gym        No         5/2/2011       6/30/2011

Итак, LINQ, который я собрал, выглядит следующим образом:

var query = from s in db.Structures
            join a in db.Activities on s.Structure_ID equals a.Structure_ID into sa
            from allStructs in sa.DefaultIfEmpty()       // I believe this is how to get the outer join and flatten the selection?
            where s.PARK == 'Elwood' && allStructs.CONTRACT_NO != ''
            orderby s.Structure_ID
            group s by s.Structure_ID into g
            select new
            {
                myID = g.Key,
                myDesc = //I don't know how to display the s.Title here ,
                myPhoto = // I don't know how to display the s.Photo here ,
                myStartDate = g.Min(c => c.START_DATE),
                myEndDate = g.Max(c => c.FINISH_DATE)
            };

Итак, теперь по вопросам:

  1. Одна вещь, которая мне не ясна в LINQ, это не то, что, когда соединение выполнено, я получаю единственную коллекцию, которая имеет столбцы ALL DECLARED, как если бы я получала стандартную инструкцию SQL, возвращающую выбор.Это смущает меня.Может ли кто-нибудь подсказать мне, правда это или нет?Похоже, я должен иметь возможность «видеть» все столбцы в объекте «allStructs» ... но это явно не тот случай.

  2. Другая серьезная проблема, с которой я борюсь, этокак показать столбцы из одного файла - я не могу просто найти способ перейти к этим полям.(Какого рода связи в # 1 выше.)

  3. Наконец, есть ли некоторые хорошие «уловки» или инструменты, которые вы можете пройти по каждой строке в выражении LINQ, как вы можете вотладчик для прямого кода C #?Когда это выражение LINQ попадает в обычный отладчик в VS, оно просто выделяет введенное выражение, и вы не можете реально ВИДЕТЬ, что происходит, когда все настраивается / выполняется.(Я понимаю, что здесь может быть много вопросов.) В настоящее время я просто использую консоль, чтобы увидеть вещи после того, как выражение приведено в движение, например, выполнить query.Count () или что-то в этом роде.

Я был бы очень признателен за любую помощь в получении лучшего понимания того, как данные преобразуются с помощью этого процесса LINQ.Я много читал здесь, MSDN и купил пару книг, но я не получил тот «момент лампочки», который, кажется, все указывают, придет.

Спасибо всем ...: -)

Ответы [ 2 ]

1 голос
/ 21 мая 2011
  1. После join у вас есть доступ к s (текущая структура) и sa, группе действий для этого Structure_ID.После DefaultIfEmpty() у вас есть доступ к тем же s и теперь allStructs, которые точно соответствуют m в вашем исходном примере SQL.Вы никогда не получите единственную переменную, которая представляет все столбцы в обеих таблицах, но вы не получите это и в SQL.

  2. Я считаю, что LINQ to SQL достаточно умен для перевода группированияна составном ключе, и в этом случае это то, что вы, вероятно, хотите:

    var query = from s in db.Structures
                join a in db.Activities on s.Structure_ID equals a.Structure_ID into sa
                from m in sa.DefaultIfEmpty() // LEFT OUTER JOIN
                where s.PARK == 'Elwood' && m.CONTRACT_NO != ''
                orderby s.Structure_ID
                group m by new { s.Structure_ID, s.Title, s.Photo } into g
                select new
                {
                    myID = g.Key.Structure_ID,
                    myDesc = g.Key.Title,
                    myPhoto = g.Key.Photo,
                    myStartDate = g.Min(c => c.START_DATE),
                    myEndDate = g.Max(c => c.FINISH_DATE)
                };
    

    Обратите внимание, что я переключил allStructs на m для согласованности с вашим SQL, и переключил group by для использования m вместо s.Значения m - это то, что будет содержаться в группах g, а Key представляет кортеж Structure_ID, Title и Photo.

  3. Для отладки лучше всего включить ведение журнала (свойство DataContext.Log), чтобы увидеть, какой SQL генерируется.Вы также можете использовать SQL Profiler.Иногда это помогает логически разобраться с коллекциями в памяти и LINQ to Objects, с оговоркой, что вы можете достичь вещей в памяти, которые вообще не переводятся в SQL.

0 голосов
/ 21 мая 2011

Чтобы ответить на ваш второй вопрос, я думаю, вы можете сделать следующее:

myDesc = g.First().Title
myPhoto = g.First().Photo
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...