Как я могу сократить этот запрос LINQ к SQL? - PullRequest
1 голос
/ 05 января 2010

Я делаю календарь, чтобы облегчить себе жизнь, я разбиваю встречи на несколько недель.

Например, с 1 января по 31 января, например, 6 недель (в моем календаре всегда 42 ячейки - 6 на 7). Таким образом, в моей базе данных было бы 6 строк.

Однако кое-что я требую от меня, чтобы собрать все эти ряды обратно в один ряд. Например, если я хочу экспортировать свой календарь в формате Ical.

У меня есть поле в моей базе данных с именем bindingClassName, все эти строки получают одинаковый идентификатор unquie для этой группы задач, поэтому я могу легко получить все недели.

// get all of the task rows by binding class name.
            var found = plannerDb.Calendars.Where(u => u.UserId == userId && u.BindingClassName == bindingClassName)
                .GroupBy(u => u.BindingClassName);



            List<Calendar> allAppoingments = new List<Calendar>();

            // go through each of the results and add it to a list of calendars
            foreach (var group in found)
            {

                foreach (var row in group)
                {

                    Calendar appointment = new Calendar();
                    appointment.AppointmentId = row.AppointmentId;
                    appointment.AllDay = row.AllDay;
                    appointment.BindingClassName = row.BindingClassName;
                    appointment.Description = row.Description;
                    appointment.EndDate = row.EndDate;
                    appointment.StartDate = row.StartDate;
                    appointment.Title = row.Title;
                    appointment.Where = row.Where;
                    appointment.UserId = row.UserId;

                    allAppoingments.Add(appointment);
                }
            }
            // order 
           var test = allAppoingments.OrderBy(u => u.StartDate);

           var firstAppointment = test.First();
           var LastAppointment = test.Last();

           Calendar newAppointment = new Calendar();
           newAppointment.UserId = firstAppointment.UserId;
           newAppointment.Description = firstAppointment.Description;
           newAppointment.AllDay = firstAppointment.AllDay;
           newAppointment.StartDate = firstAppointment.StartDate;
           newAppointment.Title = firstAppointment.Title;
           newAppointment.Where = firstAppointment.Where;
           newAppointment.BindingClassName = firstAppointment.BindingClassName;
           newAppointment.EndDate = LastAppointment.EndDate;

            return newAppointment;

Так что в основном этот большой шарик находит все встречи с одинаковым обязательным именем. Затем я прохожу каждый из них и превращаю его в объект Calendar, а затем, наконец, после того, как все это сделано, я получаю первую и последнюю запись, чтобы получить startDate и endDate.

Так что я не очень хорошо разбираюсь в linq, но я не уверен, могу ли я просто добавить что-то после groupBy, чтобы делать то, что я хочу.

Edit.

Я пытаюсь сгруппировать все встречи, как только получу их от пользователя.

Итак, у меня есть это пока

Я пробовал что-то подобное.

    var allApointments = calendar.GetAllAppointments(userId);
    var group = allApointments.GroupBy(u => u.BindingClassName).Select(u => new Calendar()).ToList

Я надеялся, что это заполнит каждую группу автоматически, но это не так. Так что я не уверен, что снова не нужен групповой.

Edit @ admin

Привет, спасибо за объяснение сортировки и группировки. Как ты это объяснил, хотя кажется, что любой из них сработает.

Как и у вас есть код для получения первого и последнего свидания, прекрасно работает и делает то, что я хотел.

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

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

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

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

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

Ответы [ 2 ]

4 голосов
/ 05 января 2010

Почему вы группируете встречи, если вы на самом деле не используете группу?Похоже, вы просто используете их по отдельности.В любом случае, вы уже фильтруете строки по одному значению для BindingClassName в предложении Where, так что вы все равно получите только 1 (или 0) группу (ы).

Вы можете переписать эту серию циклов foreach в Select и ToList() следующим образом:

var allAppointments = 
    plannerDb.Calendars.Where(
    row => row.UserId == userId && 
           row.BindingClassName == bindingClassName).OrderBy(
    row => row.StartDate).Select(
    row => new Calendar()
    {
        AppointmentId = row.AppointmentId,
        AllDay = row.AllDay,
        BindingClassName = row.BindingClassName,
        Description = row.Description,
        EndDate = row.EndDate,
        StartDate = row.StartDate,
        Title = row.Title,
        Where = row.Where,
        UserId = row.UserId
    }).ToList();

Это вернет вам полный список в нужном вам порядке.Однако мне любопытно, почему вы извлекаете весь список, когда он выглядит , как будто вы заинтересованы только в первом и последнем назначении.Вместо этого вы можете сделать это:

var baseQuery = 
        plannerDb.Calendars.Where(
        row => row.UserId == userId && 
               row.BindingClassName == bindingClassName);

var first = baseQuery.OrderBy(row => row.StartDate).First();
var last = baseQuery.OrderByDescending(row => row.StartDate).Select(
           row => row.EndDate).First();

return new Calendar()
{
    AppointmentId = first.AppointmentId,
    AllDay = first.AllDay,
    BindingClassName = first.BindingClassName,
    Description = first.Description,
    EndDate = last,
    StartDate = first.StartDate,
    Title = first.Title,
    Where = first.Where,
    UserId = first.UserId
});

Это должно привести к выводам, которые совпадают с тем, что у вас есть сейчас.Я хотел бы спросить, однако, если это именно то, что вы хотите.Допустим, у вас есть две встречи:

  • Встреча 1 начинается 5 января и заканчивается 10 января
  • Встреча 2 начинается 6 января и заканчивается 7 января

Используя эту (и вашу) логику, вы получите конечную дату 7 января, так как Встреча 2 имеет большую дату начала, но Встреча 1 фактически заканчивается позже.Я бы порекомендовал изменить второй запрос следующим образом:

var last = baseQuery.OrderByDescending(row => row.EndDate).Select(
           row => row.EndDate).First();

Это даст вам наибольшую дату окончания , что, я думаю, то, что вы на самом деле ищете.

РЕДАКТИРОВАТЬ

Я думаю, вы совершаете ( очень распространенную ) ошибку, путая группировку с сортировкой.Когда вы говорите, что хотите «сгруппировать встречи по имени привязки», это звучит так, как будто вы хотите получить полный и полный список встреч, и вы хотите, чтобы эти встречи были организованы таким образом, чтобы все встречи с определенным именем привязки образовывали смежныеблок.Если это так, вы хотите упорядочить список по имени привязки, а не группировать их.Группировка занимает весь список и создает одну строку на каждое условие группировки и позволяет выполнять функции агрегации для оставшихся столбцов.Например, скажем, я группирую встречи по имени привязки.Это означает, что мой набор результатов будет содержать по одной строке на имя привязки , и тогда я смогу найти максимальную дату начала или окончания или что-то в этом роде;более формально, вы можете указать операции агрегации, которые являются операциями, которые принимают набор данных (т.е. список дат начала) и возвращают один фрагмент данных (то есть максимальную дату начала).

Если только я 'м недопонимание, похоже, что вы все еще хотите получить все отдельные назначения, вы просто хотите, чтобы они были упорядочены по имени привязки.Если дело обстоит именно так, просто OrderBy(row => row.BindingName), и это поможет.Кроме того, вы можете не использовать слово «группа», так как люди подумают, что вы имеете в виду группу, которую я описал выше.

0 голосов
/ 06 января 2010

Так же, как побочный вопрос, не касающийся linq, вы смотрели на AutoMapper ?В настоящее время я использую это для заполнения объектов данных из linq, и я нашел, что это действительно полезно для избавления от больших разделов кода, где вы просто отображаете в dtos.Это не сделает части запроса вашего кода более короткими, но уменьшит:

return new Calendar()
{
    AppointmentId = first.AppointmentId,
    AllDay = first.AllDay,
    BindingClassName = first.BindingClassName,
    Description = first.Description,
    EndDate = last,
    StartDate = first.StartDate,
    Title = first.Title,
    Where = first.Where,
    UserId = first.UserId
});

до:

return Mapper.Map(first,new Calendar{EndDate = last});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...