gpt4 book ai didi

sql-server - 使用 ASP.NET Core 3.0 和 SQL Server 2019+ 时,我什么时候应该使用 MultipleActiveResultSets=True?

转载 作者:行者123 更新时间:2023-12-03 14:23:47 24 4
gpt4 key购买 nike

我编写的大多数应用程序不使用 MultipleActiveResultSets=True ,但我已经看到在其中几个和一些教程中启用了该选项。
这个 SO question 处理相同的主题,但它很旧,我相信在此期间情况发生了很大变化。
OP 争论执行一些非查询,同时执行 ExecuteReader 。在这种情况下,我认为这是一个糟糕的设计,因为它可能会被一些批处理样式的操作取代,也许是一个存储过程,以最大限度地减少往返次数。
当将 Entity Framework 与 ASP.NET Core 一起使用并收到与已在范围内执行某些内容的数据上下文相关的异常时,我将其视为错误而不考虑启用 MARS。
与MARS工作时读了这MS Docs article我看到一个要注意的各个方面,如选项(ANSI_NULLSDATE_FORMATLANGUAGETEXTSIZE),安全性上下文,当前的数据库,状态变量(@@ERROR@@ROWCOUNT@@FETCH_STATUS@@IDENTITY)启用。
此外,如果确实需要,10 年以上意味着功能更强大的服务器能够保持更多连接(缓存应该有助于减少这种需求)。
所以我想知道在使用现代 ASP.NET Core 应用程序 (3.0+) 时是否必须考虑启用 MARS。
问题: 使用 ASP.NET Core 3.0 和 SQL Server 2019+ 时,我什么时候应该使用 MultipleActiveResultSets=True?
编辑以解决反馈
我对详尽的分析不感兴趣,但有几个合适的上下文来证明是否使用 MARS 是合理的。
ASP.NET Core 应用程序中的一个典型示例是将数据库上下文作为范围(每个请求从连接池获取一个数据库连接,进行更改,通常每个请求/范围一个事务)。到目前为止,我已经将与每个连接的多个查询相关的错误视为我自己的错误,以避免 MARS,但我这样做了,但我没有真正理解原因。

最佳答案

是的,MARS 在现代数据访问框架中仍然占有一席之地,因为它们提供了以下两个主要一般查询问题的(高效)解决方案 - 流(即非缓冲)(1)具有急切加载相关数据集合的数据和(2)懒惰加载任何类型的相关数据。

在这两种情况下,执行查询预计会提供 IEnumerator<T>(或其异步版本),它是数据读取器(或数据库前向只读游标)的对象等价物。因此,每个 MoveNext{Async} 都应该映射到数据读取器的 ReadNext ,并且预计会提供一个完全填充的 T ,而没有缓冲在所有其他人之前。为了实现这一点,底层数据读取器必须在枚举期间保持打开状态,并在完成或提前中止时关闭(例如, FirstOrDefault() )——原因之一 IEnumerator<T>IDisposable
现在想象一下如果您启用了延迟加载会发生什么。您获得一些实体并访问一些导航属性。这就触发了延迟加载操作,当然需要执行reader从数据库中获取数据。由于外部阅读器仍处于打开状态(事件),因此在没有 MARS 的情况下,此操作只会因运行时异常而失败。不好。除了提前缓冲所有内容(基本上切换到快照模式)或不使用延迟加载之外,您或框架无能为力。
假设您不使用延迟加载(无论如何都不推荐)。但是您的实体包含相关的数据集合,并且您希望预先加载它们。关系数据库 SQL 提供平面结果集,即不支持查询结果集中的“嵌套集合”。那么如何流式传输这些数据呢?
基本上有两种解决方案。
首先是基于包含所有主 + 相关表列的单个 SQL 查询,并返回某种混合记录,其中某些字段适用于特定结果而其他字段为空值。 EF6 和 EF Core 3.0+ 使用此方法。 EF Core 1.x/2.x 使用另一种方法,EF Core 5.0 允许您在两者之间进行选择。为什么?因为当您有多个子集合时,这往往会产生非常低效的查询(执行和处理结果集,因为它传输了大量不必要的数据)。
其次是使用单独的查询——一个用于主结果集,一个用于每个相关的子集合。这个想法很简单。由于通常 PK 和 FK 都被索引,因此数据库可以使用索引有效地返回按这些列排序的它们(无论如何 join 操作都需要),然后它们可以通过预读(缓冲)最多一条记录轻松地在客户端合并。
听起来不错,不是吗?有一个小而重要的警告——它需要火星!否则,它必须切换到缓冲模式。这完全违背了 IEnumerator 和异步版本的想法 - 取消概念。您可以在我对 How can I abort a running EF Core Query using GetAsyncEnumerator? 的回答中看到后者的效果,最后的建议是启用 MARS。
有关 EF Core 查询的更多信息,请参阅官方 EF Core 文档的 Split queriesHow Queries Work(以及基本上整个 Query data )部分。
旁注 单独的连接并不是一个真正的选择,特别是如果一个人需要像可重复读取这样的事务级别。 MARS 提供了连接所需的精确抽象。 SP 中的 AFAIK 可以同时打开任意数量的游标,因此不确定 ADO 连接层的确切问题是什么,以及为什么 MARS 被认为是需要启用的可选功能,而不仅仅是开箱即用的功能。不过,ORM 可以在适用时尝试在幕后使用单独的连接。 EF Core 目前没有。

所以简单回顾一下,如果您不使用延迟加载(可能)并且没有相关集合(不太可能 - 一对多很常见,并且相关集合不一定意味着导航属性和 Include - 相同适用于对列表和类似成员的预测),那么您不需要 MARS。否则最好启用它们 - 它们是功能,所以使用它。

关于sql-server - 使用 ASP.NET Core 3.0 和 SQL Server 2019+ 时,我什么时候应该使用 MultipleActiveResultSets=True?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59607616/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com