将Asp.net应用程序更新为Npgsql 3并删除Preload Reader

我已将我的ASP.NET应用程序从NpgSQL 2.2.5更新为3.0.1。 在重大更改中,它指定已删除Preload Reader支持。 所以我从字符串连接中删除它。 测试我的网络应用程序,我收到错误“操作已在进行中”。 特别是在这样的linq查询中

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() }; 

要解决此错误,我必须在GetPlugins方法之后附加ToList 。 这是没有Preload Reader的正确行为吗? 为什么?

在Npgsql 2.x中,使用Preload Reader使Npgsql将查询的整个结果集从数据库中拉入应用程序的内存中。 这释放了连接并允许在仍然遍历第一个查询的结果集时执行另一个命令。 换句话说,它允许您编程,就好像您可以同时执行多个查询(有时称为MARS),尽管在幕后这实现效率低下。

添加ToList()完全相同 – 将所有东西都拉到客户端内存中,只发生在应用程序代码而不是数据库驱动程序中。 因此,将您的应用程序从Npgsql 2.x移植到3.x绝对是一种可接受的方式。

现在,如果拉动结果集(在本例中为GetPlugins)很小,这是一种非常有效的方法。 如果它很大,你应该考虑其他选择。 在您的示例中,可以将连接发送到数据库,使您的Linq表达式转换为单个SQL查询,并且无需多个查询(ORM,例如Entity Framework通常可以为您执行此操作)。 更极端的解决方案是使用多个数据库连接,但如果您正在使用事务,则会更重,也会出现问题。

请注意,在Npgsql中实现真正的MARS存在一个问题(虽然不太可能很快实现): https : //github.com/npgsql/npgsql/issues/462