Пейджинг с Entity Framework 7 и SQL Server 2008

Я пытаюсь использовать пейджинг (то есть .Skip(...).Take(...) в Entity Framework 7. Он работает нормально с Microsoft SQL Server 2012 и 2014, но не работает со следующей ошибкой на SQL Server 2008:

System.Data.SqlClient.SqlException (0x80131904): неправильный синтаксис рядом с «СМЕЩЕНИЕМ». Недопустимое использование параметра NEXT в операторе FETCH.

Я выяснил, что это критическое изменение в EF версии 6.1.2 (http://erikej.blogspot.com/2014/12/a-breaking-change-in-entity-framework.html). Но исправление заключается в изменении атрибута ProviderManifestToken файла EDMX на «2008».

Проблема в том, что EF7 в настоящее время поддерживает только сценарий code-first, поэтому EDMX отсутствует. Возникает вопрос: как настроить веб-сайт ASP.NET 5 с Entity Framework 7 для использования резервного разбиения на страницы для SQL Server старше 2012 года?


person Konstantin    schedule 01.05.2015    source источник
comment
См. вопрос #1326 и добавьте любые комментарии, которые у вас могут быть.   -  person bricelam    schedule 04.05.2015


Ответы (7)


Я сам столкнулся с этой проблемой, используя EF 7 и sql server 2008. К счастью, в последней версии EF 7 rc1 вы можете решить эту проблему, используя .UseRowNumberForPaging(), как показано в этом примере:

services.AddEntityFramework()
  .AddSqlServer()
  .AddDbContext<YourDbContext>(options =>
     options.UseSqlServer(configuration["Data:DefaultConnection:ConnectionString"])
                    // this is needed unless you are on mssql 2012 or higher
                    .UseRowNumberForPaging()
                );
person Joe Audette    schedule 08.12.2015
comment
Я сделал это, и я все еще сталкиваюсь с указанной ошибкой. - person Mickael Caruso; 21.12.2015
comment
Не работает в RC 1. Linq Skip по-прежнему пытается сгенерировать синтаксис OFFSET/FETCH NEXT. - person Simon Ordo; 29.04.2016

Если вы используете файл Edmx, вы должны открыть файл edmx с помощью редактора XML и изменить

ProviderManifestToken="2012" ==> ProviderManifestToken="2008"

в строке 7.

Дополнительную информацию см. в этом сообщении в блоге: http://erikej.blogspot.com.tr/2014/12/a-breaking-change-in-entity-framework.html

person mesut    schedule 30.05.2015
comment
Спасибо. Та же проблема решена, когда моя база данных Azure была взята из локальной базы данных. - person Rajaram Shelar; 09.06.2015
comment
Это сэкономило мне так много времени, и это заслуживает гораздо большего внимания. В моем случае моей средой разработки был SQL SERVER 2012, а моей средой контроля качества — 2008 R2. - person Khan; 29.10.2015
comment
Если он изменится на 2008, будет ли он по-прежнему работать с SQL Server 2012? - person Yusril Maulidan Raji; 30.05.2017
comment
Подтвержденный. Это работает и для SQL Server 2012. Теперь я верю, что этот ответ с небес! - person Yusril Maulidan Raji; 30.05.2017
comment
На дворе 2019 год, а это исправление до сих пор отлично работает. Теперь я хочу, чтобы кто-нибудь просто обновил нашу БД с 2008 года... Давайте, администраторы баз данных, вы можете это сделать. :) - person SammyRNYCreal; 10.04.2019

Он сломан в RC 1. Надо подождать, чтобы получить RC 2.

https://github.com/aspnet/EntityFramework/issues/4616

person Simon Ordo    schedule 29.04.2016
comment
Очень полезная ссылка. Это помогло мне решить мою проблему, используя: options.UseSqlServer(connection, b => b.UseRowNumberForPaging()); - person marianc; 12.08.2016
comment
Очень полезно! useRowNumberForPaging() решил мою проблему! - person wtf512; 01.04.2017

MyDbConnectionString – это строка подключения из любого источника.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(_config["MyDbConnectionString"], 
                options=>
                {
                    options.UseRowNumberForPaging();
                });
}

UseRowNumberForPaging() проблема решена в любом случае, кроме сценария с файлом edmx.

person Salman Taj    schedule 30.07.2018
comment
Поскольку SQL Server 2008 не поддерживает FETCH, а FETCH OFFSET требует orderby() skip() и take() - person Salman Taj; 30.07.2018

Эта функция удален в EF Core 3.x, UseRowNumberForPaging помечен как устаревший. Однако вместо этого вы можете использовать пакет EfCore3.SqlServer2008Query. В Nuget доступно 2 пакета: один для ›= .NET 5.0, другой для ›= .NET 3.1.

введите здесь описание изображения

Использование:

 services.AddDbContext<MyDbContext>(o => 
       o.UseSqlServer(Configuration.GetConnectionString("Default"))
        .ReplaceService<IQueryTranslationPostprocessorFactory, SqlServer2008QueryTranslationPostprocessorFactory>());
person Yegor Androsov    schedule 03.02.2021

Вам нужно использовать что-то вроде этого:

var MinPageRank = (pageIndex - 1) * pageSize + 1;
var MaxPageRank = (pageIndex * pageSize);

var person = _context.Person.FromSql($"SELECT * FROM (SELECT [RANK] = ROW_NUMBER() OVER (ORDER BY Surname),* FROM Person) A WHERE A.[RANK] BETWEEN {MinPageRank} AND {MaxPageRank}").ToList();

IQueryable<Person> PersonIQ = from s in person.AsQueryable() select s;
Person = await PaginatedList<Person>.CreateAsync(PersonIQ .AsNoTracking(), pageIndex ?? 1, pageSize, sourceFull);
person Belen Martin    schedule 19.04.2018
comment
Почему вы делаете pageSize+ 1 ? - person Enrico; 19.06.2018

Здесь просто установите UseRowNumberForPaging() в ConfigureServices

services.AddDbContext<CallcContext>(options => 
options.UseSqlServer(Configuration.GetConnectionString("Connectionstring"),opt=> { opt.UseRowNumberForPaging(); }));
person Ali Besharati    schedule 13.11.2018