使用Entity Framework 6和MS-SQL Server实现连接弹性的自定义执行策略

时间:2017-08-08 09:03:47

标签: c# .net sql-server entity-framework entity-framework-6

我已经使用EF6和MS-SQL Server开发了一个应用程序。

我的应用程序中的所有地方都编写了如下代码,我需要在表格中插入,更新或删除数据:

代码:

using (DemoEntities objContext = GetDemoEntities())
{
    using (TransactionScope objTransaction = new TransactionScope())
    {

        Demo1(objContext);

        Demo2(objContext);

        // Commit the changes in the database.
        objTransaction.Complete();
    }
}

public void Demo1(DemoEntities objContext)
{
    Demo1 objDemo1 = new Demo1();
    objDemo1.Title = "ABC";

    objContext.Demo1.Add(objDemo1);

    objContext.SaveChanges();   
}

public void Demo2(DemoEntities objContext)
{
    Demo2 objDemo2 = new Demo2();
    objDemo2.Title = "ABC";

    objContext.Demo2.Add(objDemo2);

    objContext.SaveChanges();   
}

我的应用程序在一台服务器上运行,数据库正在AWS中的另一台服务器上运行。

我的应用程序运行顺利,但是弱了2-3次我得到了如下所示的错误。

  

System.Data.Entity.Core.EntityException:基础提供程序   打开失败。 ---> System.Data.SqlClient.SqlException:A   建立时发生与网络相关或特定于实例的错误   与SQL Server的连接。服务器未找到或未找到   无障碍。验证实例名称是否正确以及SQL   服务器配置为允许远程连接。 (提供者:命名   管道提供程序,错误:40 - 无法打开到SQL Server的连接)   ---> System.ComponentModel.Win32Exception:访问被拒绝

在第一个请求中我收到了上述错误,并且在另一个请求之后我没有收到任何错误并且请求成功。

在做了一些Google之后我得到了我在我的应用程序中实现的连接弹性这个概念,它可以在某个特定时期后的某些特定时间重试查询。

但是在我使用自定义事务的位置失败了,就像在上面的代码中一样。它会抛出这样的错误。

  

System.InvalidOperationException:配置的执行策略   'MYExecutionStrategy'不支持用户发起的交易。   有关其他信息,请参阅http://go.microsoft.com/fwlink/?LinkId=309381   信息。

我按照以下方式配置了执行策略:

public class MYExecutionStrategy : DbExecutionStrategy
{
    /// <summary>
    /// The default retry limit is 5, which means that the total amount of time spent 
    /// between retries is 26 seconds plus the random factor.
    /// </summary>
    public MYExecutionStrategy()
    {
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="maxRetryCount"></param>
    /// <param name="maxDelay"></param>
    public MYExecutionStrategy(int maxRetryCount, TimeSpan maxDelay)
        : base(maxRetryCount, maxDelay)
    {
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exception"></param>
    /// <returns></returns>
    protected override bool ShouldRetryOn(Exception exception)
    {
        bool bRetry = false;

        SqlException objSqlException = exception as SqlException;

        if (objSqlException != null)
        {
            List<int> lstErrorNumbersToRetry = new List<int>()
            {
                5 // SQL Server is down or not reachable
            };

            if (objSqlException.Errors.Cast<SqlError>().Any(A => lstErrorNumbersToRetry.Contains(A.Number)))
            {
                bRetry = true;
            }
        }

        return bRetry;
    }
}

和DBConfiguration一样:

/// <summary>
/// 
/// </summary>
public class MYConfiguration : DbConfiguration
{
    /// <summary>
    /// 
    /// </summary>
    public MYConfiguration()
    {
        SetExecutionStrategy("System.Data.SqlClient", () => new MYExecutionStrategy(3, TimeSpan.FromSeconds(1)));            
    }
}

问题:

  1. 如何使用自定义事务在实体框架6中使用连接弹性。
  2. 我无法找到 DatabaseFacade 类或命名空间。

2 个答案:

答案 0 :(得分:0)

如果在第二个SaveChanges()上出现连接失败,则使用自定义事务,第一个SaveChanges()也将回滚。您如何建议重试?你不能。这就是为什么EF重试仅支持每个事务的单个SaveChanges()。

前进的方法是从Demo1()和Demo2()中删除SaveChanges(),并在调用方法中使用单个SaveChanges()而不是事务。

另一种方法是在调用方法中捕获异常并在那里编排重试。

答案 1 :(得分:0)

所以在做了一些RnD并在WEB上阅读后,我找到了这样的解决方案:

ReadString