Что такое LINQ, чтобы выбрать последний элемент из ряда элементов с версионным статусом? - PullRequest
3 голосов
/ 18 ноября 2010

У меня есть класс, подобный следующему:

public class Invoice
{
    public int InvoiceId {get;set;}
    public int VersionId {get;set;}
}

Каждый раз, когда Invoice изменяется, VersionId увеличивается, но InvoiceId остается тем же.Итак, с учетом IEnumerable<Invoice>, который имеет следующие результаты:

InvoiceId VersionId
1         1
1         2
1         3
2         1
2         2

Как получить только результаты:

InvoiceId VersionId
1         3
2         2

Т.е. я хочу получить только счета-фактуры от результатов, которыепоследняя версияЯ легко могу сделать это в T-SQL, но не могу на всю жизнь выработать правильный синтаксис LINQ.Сначала я использую Entity Framework 4 Code.

Ответы [ 3 ]

1 голос
/ 18 ноября 2010

Порядок по VersionId, сгруппируйте их по InvoiceId, затем возьмите первый результат каждой группы. Попробуйте это:

var query = list.OrderByDescending(i => i.VersionId)
                .GroupBy(i => i.InvoiceId)
                .Select(g => g.First());

РЕДАКТИРОВАТЬ: как насчет этого подхода с использованием Max?

var query = list.GroupBy(i => i.InvoiceId)
                .Select(g => g.Single(i => i.VersionId == g.Max(o => o.VersionId)));

Попробуйте также использовать FirstOrDefault или SingleOrDefault вместо Single ... это даст тот же результат, хотя Single лучше показывает намерение.

1 голос
/ 18 ноября 2010

Моя версия:

var h = from i in Invoices
        group i.VersionId by i.InvoiceId into grouping
        select new {InvoiceId = grouping.Key, VersionId = grouping.Max()};

Обновление

Как отметил Ахмад в комментариях, приведенный выше запрос вернет прогноз. Версия ниже вернет IQueryable<Invoice>. Я использую композицию для построения запроса, потому что думаю, что он более понятен.

var maxVersions = from i in Invoices
                  group i.VersionId by i.InvoiceId into grouping
                  select new {InvoiceId = grouping.Key, 
                              VersionId = grouping.Max()};

var latestInvoices =  from i in Invoices
                      join m in maxVersions 
                      on new {i.InvoiceId, i.VersionId} equals 
                         new {m.InvoiceId, m.VersionId}
                      select i;
1 голос
/ 18 ноября 2010

РЕДАКТИРОВАТЬ: я протестировал оба этих запроса с LINQ to Entities. Кажется, они работают, так что, возможно, проблема в чем-то еще?


Вариант 1:

var latestInvoices = invoices.GroupBy(i => i.InvoiceId)
                             .Select(group => group.OrderByDescending(i => i.VersionId)
                                                   .FirstOrDefault());

РЕДАКТИРОВАТЬ: изменено «Last» на «FirstOrDefault», LINQ to Entities имеет проблемы с оператором запроса «Last».


Вариант 2:

var invoices = from invoice in dc.Invoices
               group invoice by invoice.InvoiceId into invoiceGroup
               let maxVersion = invoiceGroup.Max(i => i.VersionId)
               from candidate in invoiceGroup
               where candidate.VersionId == maxVersion
               select candidate;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...