将 Asp.net 应用程序更新到 Npgsql 3 并移除 Preload Reader
Update Asp.net app to Npgsql 3 and removing Preload Reader
我已将我的 ASP.NET 应用程序从 NpgSQL 2.2.5 更新到 3.0.1。在重大更改中,指定他们已删除 Preload Reader 支持。所以我将它从字符串连接中删除。
测试我的网络应用程序时,我在 linq 查询 中得到了错误 "An operation is already in progress.",如下所示:
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 查询并消除对多个查询的需要(诸如 Entity Framework 之类的 ORM 通常可以为您完成此操作) .更极端的解决方案是使用多个数据库连接,但如果您使用的是事务,那会更重并且也会有问题。
请注意,在 Npgsql 中实现真正的 MARS 存在一个问题(尽管不太可能很快实现):https://github.com/npgsql/npgsql/issues/462
我已将我的 ASP.NET 应用程序从 NpgSQL 2.2.5 更新到 3.0.1。在重大更改中,指定他们已删除 Preload Reader 支持。所以我将它从字符串连接中删除。 测试我的网络应用程序时,我在 linq 查询 中得到了错误 "An operation is already in progress.",如下所示:
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 查询并消除对多个查询的需要(诸如 Entity Framework 之类的 ORM 通常可以为您完成此操作) .更极端的解决方案是使用多个数据库连接,但如果您使用的是事务,那会更重并且也会有问题。
请注意,在 Npgsql 中实现真正的 MARS 存在一个问题(尽管不太可能很快实现):https://github.com/npgsql/npgsql/issues/462