Ariel Quiroz Ответов: 2

Entityframework > операторы skip и take не работают


Я реализую функцию для разбиения на страницы. Я использую операторы skip и take для достижения этой цели.
Моя проблема заключается в следующем:
Я создал функцию для разбиения на страницы. Например:
public List<SomeEntity> Paginate(int skipValue, int takeValue, Expression<Func<SomeEntity, bool>> predicate)
{
    _context.SomeEntity
            .Where(predicate)
            .OrderByDescending(t => t.DateCreate)
            .Skip(skipValue)
            .Take(takeValue)
            .ToList();
}

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

На всякий случай я создал веб-приложение. Затем мой контроллер вызывает эту функцию.

Кто - то знает, потому что кэширует значения из skip и take??

Что я уже пробовал:

Я не знаю, потому что происходит эта ошибка.

F-ES Sitecore

Пропустите и возьмите *do* work, так что проблема находится в другом месте вашего кода. Вы либо не передаете правильные значения в функцию, либо передаете значения, отличные от того, что вы думаете, либо проблема может быть с другой функцией. Вам придется использовать отладчик, чтобы лучше понять, что происходит. Кроме того, используйте трассировку SQL для изучения фактического выполнения SQL, что может дать вам лучшее представление о том, что происходит.

2 Ответов

Рейтинг:
1

Ariel Quiroz

Я решил этот путь:

public List<SomeEntity> Paginate(int skipValue, int takeValue, 
                                 Expression<Func<SomeEntity, bool>> predicate)
{
  var res =_context.SomeEntity
            .Where(predicate)
            .OrderByDescending(t => t.DateCreate)
            .ToList();

   return res.Skip(skipValue).Take(takeValue).ToList();  
}


Мне не нравится это решение. Я не понимаю, потому что это не работает таким образом:

_context.SomeEntity
            .Where(predicate)
            .OrderByDescending(t => t.DateCreate)
            .Skip(skipValue)
            .Take(takeValue)
            .ToList();


Рейтинг:
1

Dave Kreskowiak

Посмотрите на свой код Skip and Take и сравните имена переменных, используемые в этих вызовах, с именами переменных, переданными в заголовок метода Paginate.

public List<SomeEntity> Paginate(int skip, int take, Expression<Func<SomeEntity, bool>> predicate)

по сравнению с
.Skip(skipValue)
.Take(takeValue)

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

Кстати, с помощью отладчика на этом коде было бы очень легко выяснить, где находится проблема.


Ariel Quiroz

Извините, я плохо написал. Имена переменных одинаковы.

Ariel Quiroz

общественная список<someentity&ГТ; нумеровать(инт skipValue, takeValue инт выражение&ЛТ;изм&ЛТ;SomeEntity, типа bool&ГТ;&ГТ; сказуемое)
{
_context.SomeEntity
.Где(сказуемое)
.OrderByDescending(Т =&ГТ; Т.DateCreate)
.Skip(skipValue)
.Take(takeValue)
.Список();
}

Dave Kreskowiak

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

Richard Deeming

Где же это return ключевое слово в этой функции?

Dave Kreskowiak

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

Код даже не будет компилироваться, если оператор return отсутствует.

Ariel Quiroz

Да, я использовал отладчик, даже я напечатал эти переменные и всегда меняюсь.

Dave Kreskowiak

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

Это то, в чем тебе придется покопаться. Никто не сможет сделать это за вас или сказать вам, что с этим не так.

Ariel Quiroz

Являются ли они одинаковыми значениями при каждом проходе через метод? Нет, они меняются. Я реализую webApi, а затем из своей конечной точки вызываю этот метод.
Данные не меняются, Но да, переменные skipValue и takeValue.
Я новичок в EntityFramework и netCore, но думаю, что ошибка кроется в моем контексте или в моем DbSet. Потому что так оно и работает.

var res =_context.SomeEntity.Where(predicate)
                            .OrderByDescending(t => t.DateCreate)            
                            .ToList();   
return res.Skip(skipValue).Take(takeValue).ToList();

Dave Kreskowiak

Ошибка не будет находиться в контексте или коде класса сущностей.

Меняется ли возвращаемое существо? Или это просто игнорируется вашим клиентским кодом для обновления дисплея?

Чтобы узнать это, сделайте это в коде, который вы только что опубликовали:

var res =_context.SomeEntity
    .Where(predicate)
    .OrderByDescending(t => t.DateCreate)
    .Skip(skipValue)
    .Take(takeValue)
    .ToList();

return res;

Поставьте точку останова в строке возврата и запустите код. Наведите указатель мыши на переменную res, когда отладчик прерывается, чтобы увидеть данные, возвращаемые клиенту. Если это не та страница, которой она должна быть, вам нужно навести курсор мыши на переменные skipValue и takeValue, чтобы увидеть их содержимое и проследить через код обратно к клиенту, чтобы выяснить, почему эти значения передаются.

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

Никто здесь не может сделать это за вас, потому что мы не видим никакого вашего кода, кроме того, что вы публикуете здесь. У нас также нет ваших данных, базы данных, ввода в приложение ... ничего.

Мы ничего не можем сделать для вас.

Ariel Quiroz

Очевидно, я поставил много точек останова.
Примером может служить следующее.
Мой код таков:

1 var res =_context.SomeEntity
2                  .Where(predicate)
3                  .OrderByDescending(t => t.DateCreate)
4                  .Skip(skipValue)
5                  .Take(takeValue)
6                  .ToList();
7
8     return res;


Первый раз:
Ввод:
Данные: A, B, C, D, E, F, G, H, I, J.
skipValue = 0
takeValue = 2
Выход:
res = A, B

Второй раз:
Данные: A, B, C, D, E, F, G, H, I, J.
skipValue = 3
takeValue = 2
Выход:
res = A, B

Третий раз:
Данные: A, B, C, D, E, F, G, H, I, J.
skipValue = 5
takeValue = 2
Выход:
res = A, B

Надеюсь, вы меня понимаете.
Спасибо за вашу помощь.

Dave Kreskowiak

Этот запрос работает. Я просто попробовал его против моей собственной базы данных, и он работал, как и ожидалось. Я настоятельно рекомендую вам создать небольшое тестовое приложение для проверки вашего контекста. Что-то вроде этого:

        static void Main(string[] args)
        {
            int skip = 0;
            int take = 5;

            for (skip = 0; skip <= 20; skip+=take)
            {
                var table = GetPage(skip, take);
                DumpTablePage(skip, take, table);
            }

            Console.WriteLine("Press ENTER to quit...");
            Console.ReadLine();
        }

        static void DumpTablePage(int skipValue, int takeValue, IEnumerable<MyEntityClass> tablePage)
        {
            Console.WriteLine($"Page starts at {skipValue} and runs for {takeValue} records:");
            foreach (MyEntityClass item in tablePage)
            {
                Console.WriteLine($"\t{item.NameProperty}");
            }
        }

        static IEnumerable<MyEntityClass> GetPage(int skipValue, int takeValue)
        {
            using (MyContextClass context = new MyContextClass())
            {
                // Setup the SQL query.
                var query = context.MyEntityClass
                            .Where(x => x.Status != "Retired")
                            .OrderByDescending(x => x.Id)
                            .Skip(skipValue)
                            .Take(takeValue);

                // Execute the query.
                var result = query.ToList();

                // Return the data.
                return result;
            }
        }