Узнайте, на какой странице находится элемент

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

public IEnumerable<Sample> GetPageData(int orderId, int page, int itemsPerPage)
{
    var samples = _context.Set<Sample>()
                          .Where(s => s.OrderId == orderId)
                          .OrderBy(s => s.Id)
                          .Skip(itemsPerPage * page)
                          .Take(itemsPerPage);

    return samples;
}

Я хотел бы иметь другой метод репозитория, чтобы я мог получить страницу, на которой находится образец. Подпись метода будет выглядеть примерно так:

public int GetPage(int orderId, int sampleId, int itemsPerPage)
{
    // ???
}

Я изо всех сил пытаюсь найти способ сделать это в LINQ. Единственная идея, которую я имею сейчас, - это получить страницы один за другим, пока не найду нужный образец. Я знаю, что это не эффективно, но требование состоит в том, что не более 500 образцов, а размер страницы - 25.

Как я мог бы сделать это более эффективно?

Ответы

Ответ 1

public int GetPage(int orderId, int sampleId, int itemsPerPage)
{
    //protect against divide by zero
   if(itemsPerPage < 1)
      return 1;//or 0 if you want page index

  int index = _context.Set<Sample>()
                       .Where(s => s.OrderId == orderId && s.Id < sampleId)
                       //.OrderBy(s => s.Id) edited after accepted OrderBy not necessary
                       .Count();

   //if index is zero return 1
   //if index == 9 and itemsPerPage == 10 return 1 
   //if index == 10 and itemsPerPage == 10 return 2
   //if you want the page index rather than the page number don't add 1
   return 1 + (index / itemsPerPage);
}

Усилия RR Lyndon заставили меня подумать еще об этом, и я придумал это как способ проверки того, что на самом деле страница содержит образец - в одном запросе к базе данных

public int GetPage(int orderId, int sampleId, int itemsPerPage)
{
    //protect against divide by zero
   if(itemsPerPage < 1)
      return 1;//or 0 if you want page index, or -1 if you want to flag this as invalid

   var result = context.Set<Sample>()
                .Where(s => s.OrderId == orderId 
                            && s.Id <= sampleId)//this time include sampleId
                //.OrderBy(s => s.ID)  edited after accepted OrderBy not necessary
                .GroupBy(x => true)
                .Select(group => new
                {
                    MaxID = group.Max(s => s.Id),
                    Count = group.Count()
                })
                .Single();

  //Check the sample is actually in the result
  if(result.MaxID != sampleId)
      return 1;//or 0 if you want page index, or -1 if you want to flag this as invalid

  int index = result.Count - 1;

   //if you want the page index rather than the page number don't add 1
   return 1 + (index / itemsPerPage);
}

Ответ 2

public int GetPage(int sampleId, int itemsPerPage)
{
    return _context.Set<Sample>()
                   .Count(s => s.Id <= sampleId) / itemsPerPage;
}

Ответ 3

public int GetPage(int orderId, int sampleId, int itemsPerPage)
{
    var samples = _context.Set<Sample>()
        .Where(s => s.OrderId == orderId)
        .OrderBy(s => s.Id)
        .Where(s => s.Id <= sampleId)
        .ToList();

    var lastSample = samples.LastOrDefault();
    if (lastSample == null || lastSample.Id != sampleId) return -1;

    return (samples.Count - 1) / itemsPerPage;
}

Ответ 4

Предполагается, что существует (по крайней мере) запись для данного образцаId и orderId.

public int GetPage(int sampleId, int itemsPerPage, int orderId)
{
   return _context.Set<Sample>().Count(s => s.OrderId == orderId && s.Id < sampleId) / itemsPerPage + 1;                
}