Номер строки в LINQ - PullRequest
6 голосов
/ 16 мая 2011

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

var accounts =
    from account in context.Accounts
    from guranteer in account.Gurantors
     where guranteer.GuarantorRegistryId == guranteerRegistryId
    select new AccountsReport
    {
        recordIndex = ?   
        CreditRegistryId = account.CreditRegistryId,
        AccountNumber = account.AccountNo,
    }

Я хочу заполнить recordIndex значением текущего номера строки в коллекции, возвращаемой LINQ.Как я могу получить номер строки?

Ответы [ 5 ]

13 голосов
/ 16 мая 2011

Номер строки не поддерживается в linq-to-entity.Сначала вы должны извлечь записи из базы данных без номера строки, а затем добавить номер строки с помощью linq-to-objects.Что-то вроде:

var accounts =
    (from account in context.Accounts
     from guranteer in account.Gurantors
         where guranteer.GuarantorRegistryId == guranteerRegistryId
     select new
         {  
             CreditRegistryId = account.CreditRegistryId,
             AccountNumber = account.AccountNo,
         })
    .AsEnumerable()  // Moving to linq-to-objects 
    .Select((r, i) => new AccountReport
         {
             RecordIndex = i,  
             CreditRegistryId = r.CreditRegistryId,
             AccountNumber = r.AccountNo,
         });
2 голосов
/ 16 мая 2011

LINQ для объектов имеет эту встроенную функцию для любого перечислителя:

http://weblogs.asp.net/fmarguerie/archive/2008/11/10/using-the-select-linq-query-operator-with-indexes.aspx

Редактировать : хотя IQueryable также поддерживает его ( здесь и здесь ) было упомянуто, что это , к сожалению, не работает для LINQ to SQL / Entities.

new []{"aap", "noot", "mies"}
    .Select( (element, index) => new { element, index });                                  

В результате:

{ { element = aap, index = 0 }, 
  { element = noot, index = 1 }, 
  { element = mies, index = 2 } }

Существуют другие методы расширения LINQ (например, .Where) с дополнительной перегрузкой параметра индекса

1 голос
/ 16 мая 2011

Попробуйте использовать let, как это:

int[] ints = new[] { 1, 2, 3, 4, 5 };
int counter = 0;
var result = from i in ints
             where i % 2 == 0
             let number = ++counter
             select new { I = i, Number = number };

foreach (var r in result)
{
    Console.WriteLine(r.Number + ": " + r.I);
}

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

Если это не поддерживается вашим конкретным провайдером, вы всегда можете использовать foreach (что приводит к выполнению запроса) и назначать номер вручную в коде.

0 голосов
/ 13 февраля 2012

Это проверено и работает:

Изменить ваш код следующим образом:

int counter = 0; 
var accounts =
    from account in context.Accounts
    from guranteer in account.Gurantors
     where guranteer.GuarantorRegistryId == guranteerRegistryId
    select new AccountsReport
    {
        recordIndex = counter++   
        CreditRegistryId = account.CreditRegistryId,
        AccountNumber = account.AccountNo,
    }

Надеюсь, это поможет .. Хотя уже поздно:)

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

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

Если вам нужен эквивалент SQL ROW_NUMBER [..] OVER [..], единственный известный мне способ - создать представление на вашем SQL-сервере и выполнить запрос к нему.

...