sql-server - 与 Entity Framework 和 transient 故障处理 block 的连接?

标签 sql-server azure entity-framework-4 azure-sql-database

我们正在将 SQL 迁移到 Azure。我们的 DAL 基于 Entity Framework 4.x。我们希望使用 transient 故障处理 block 为 SQL Azure 添加重试逻辑。

总的来说,我们正在寻找最好的 80/20 规则(或者可能更多的是 95/5,但你明白了)——我们不打算花几周的时间重构/重写代码(有很多代码) )。我很好地重新实现我们的 DAL 框架,但并不是所有针对它编写和生成的代码都比我们必须的要多,因为这已经在这里只是为了解决少数情况。缓解措施 >>> 为我们消除这种边缘情况。

查看可能的选项解释 here at MSDN ,似乎案例#3实现起来“最快”,但只是乍一看。在稍微考虑一下这个解决方案后,我突然意识到我们可能会在连接管理方面遇到问题,因为这种规避 Entity Framework 用于管理连接的内置流程(即始终关闭它们)。在我看来,“解决方案”是确保我们实例化的上下文 100% 使用 using block ,但对于我们的架构来说,这会很困难。

所以我的问题是:按照该链接中的案例#3,挂起的连接是否是一个问题,或者是否有一些我不知道的魔法正在发生?

最佳答案

我做了一些实验,结果发现这让我们回到了过去习惯的旧的“管理连接”情况,只是这一次连接被从我们身上抽象了一点,我们必须现在类似地“管理上下文”。

假设我们有以下 OnContextCreated 实现:

private void OnContextCreated()
{
    const int maxRetries = 4;
    const int initialDelayInMilliseconds = 100;
    const int maxDelayInMilliseconds = 5000;
    const int deltaBackoffInMilliseconds = initialDelayInMilliseconds;

    var policy = new RetryPolicy<SqlAzureTransientErrorDetectionStrategy>(maxRetries,
                                                                            TimeSpan.FromMilliseconds(initialDelayInMilliseconds),
                                                                            TimeSpan.FromMilliseconds(maxDelayInMilliseconds),
                                                                            TimeSpan.FromMilliseconds(deltaBackoffInMilliseconds));
    policy.ExecuteAction(() =>
            {
                try
                {
                    Connection.Open();
                    var storeConnection = (SqlConnection) ((EntityConnection) Connection).StoreConnection;
                    new SqlCommand("declare @i int", storeConnection).ExecuteNonQuery();
                    //Connection.Close();
                    // throw new ApplicationException("Test only");
                }
                catch (Exception e)
                {
                    Connection.Close();

                    Trace.TraceWarning("Attempted to open connection but failed: " + e.Message);

                    throw;
                }
            }
        );
}

在这种情况下,我们强制打开连接(这是这里的目标)。因此,上下文在多次调用中保持打开状态。因此,我们必须告诉上下文何时关闭连接。我们执行此操作的主要机制是调用 Context 上的 Dispose 方法。因此,如果我们只允许垃圾收集来清理我们的上下文,那么我们就允许连接保持打开状态。

我通过切换 try block 中 Connection.Close() 上的注释并针对我们的数据库运行一堆单元测试来对此进行测试。在不调用 Close 的情况下,我们的事件连接数跃升至约 275-300 个(从 SQL Server 的角度来看)。通过调用 Close,该数字徘徊在 ~12。然后,我使用和不使用 Context 的 using block 复制了少量单元测试,并复制了相同的结果(不同的数字 - 我忘记了它们是什么)。

我使用以下查询来计算我的连接数:

SELECT s.session_id, s.login_name, e.connection_id,
      s.last_request_end_time, s.cpu_time, 
      e.connect_time
FROM sys.dm_exec_sessions AS s
INNER JOIN sys.dm_exec_connections AS e
ON s.session_id = e.session_id
WHERE login_name='myuser'
ORDER BY s.login_name

结论:如果您使用此解决方法调用 Connection.Open() 来启用 transient 故障处理 block ,那么您必须使用 using block 来

关于sql-server - 与 Entity Framework 和 transient 故障处理 block 的连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14387953/

相关文章:

sql-server - UAT 数据应该是 Production 的镜像吗?如果是这样,怎么办?

sql-server - 在 SSIS 脚本任务中循环记录集目标

asp.net - 如何访问 Microsoft Azure 网站上上传的文件?

c# - EF4 复杂的 Select() : Return IEnumerable or IEnumerable<MyCustomDto> from Business Tier?

sql-server - SQL中的NULL和编程语言中的NULL的区别

c# - 如果在 C# 中不存在则插入

azure - 无法在 VSTS 中构建编译的 Azure 函数(错误 MSB4019)

sql-server - 没有事务的 Azure SQL 数据库上的死锁

c# - 将 DbSet 传递给参数类型为 IEnumerable<> 的方法时出现奇怪的 EF 行为

entity-framework-4 - Entity Framework 调用ToList()时会自动加载FK对象?