2015-08-31 1 views
2

Я обновил приложение ASP.NET от NpgSQL 2.2.5 до 3.0.1. В изменениях прерывания указано, что они удалили Preload Reader. Поэтому я удаляю его из строкового соединения. Тестирование моего веб-приложения, я получил сообщение об ошибке «Операция уже выполняется». специально в Linq запрос так:Обновление приложения Asp.net для Npgsql 3 и удаление Preload Reader

var plugins = 
      from p in _pluginRepository.GetPlugins() // this method return this: GetAll().OrderBy(p => p.Created) 
      join e in _userPluginRepository.GetByUserId(user.Id).ToList() on p.Id equals e.Plugin.Id into pe 
      from e in pe.DefaultIfEmpty() 
      select new PluginViewModel 
      { 
       Active = e != null, 
       Name = p.Translations.ToUserLanguage(loggedInUser), 
       Key = p.Key, 
       PluginId = p.Id, 
       SettingId = e == null ? 0 : e.Id, 
       ExpireDate = e != null && e.ExpireDate.HasValue ? e.ExpireDate.Value : (DateTime?) null, 
       Grants = e == null ? UserPluginGrants.None.GetHashCode().ToString() : e.Grants.GetHashCode().ToString() 
      }; 

Чтобы решить эту ошибку, я должен присоединять ToList после GetPlugins метода. Это правильное поведение для использования без Preload Reader? Зачем?

ответ

2

В Npgsql 2.x, используя Preload Reader, сделанный Npgsql вытащил весь набор результатов запроса из базы данных в память вашего приложения. Это освободило соединение и разрешило выполнение другой команды, продолжая перемещаться по набору результатов первого запроса. Другими словами, это позволило вам программировать, как если бы вы могли выполнять несколько запросов одновременно (иногда известный как MARS), хотя за кулисами это было реализовано неэффективно.

Добавление ToList() делает то же самое - вытащить все в клиентскую память, только это происходит в коде приложения, а не в драйвере базы данных. Таким образом, это определенно приемлемый способ переноса вашего приложения из Npgsql 2.x в 3.x.

Теперь, если результирующий набор (в данном случае GetPlugins) мал, это совершенно правильный подход. Если он большой, однако вы должны изучить альтернативы. В вашем примере соединение может быть отправлено в базу данных, что делает ваше выражение Linq переведенным в один SQL-запрос и устраняет необходимость в нескольких запросах (такие ORM, как Entity Framework, обычно могут сделать это для вас). Более экстремальным решением будет использование нескольких соединений с базами данных, но это тяжелее, а также проблематично, если вы используете транзакции.

Обратите внимание, что существует проблема открыта для реализации истинного MARS в Npgsql (хотя это, вероятно, не будет реализована в ближайшее время): https://github.com/npgsql/npgsql/issues/462