使用EF时数据库连接丢失时如何捕获异常?

问题描述

我正在从数据库中使用ADO.NET实体数据模型EF设计器。我的sql服务器在另一台PC上,当我与数据库失去连接时,我的应用程序停止了,只能将其关闭。 我得到:

System.Data.Entity.Core.EntityException
  HResult=0x80131501
  Message=The underlying provider Failed on Open.
  Source=EntityFramework

Inner Exception 1:
sqlException: A network-related or instance-specific error occurred while establishing a connection to sql Server. The server was not found or was not accessible.

Inner Exception 2:
Win32Exception: The network path was not found

有什么办法解决这个问题?

解决方法

对于弹性和自定义处理,答案是相同的。您需要配置策略:

检查连接弹性:https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency#custom-execution-strategy

以下代码可让您重试失败:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EFMiscellanous.ConnectionResiliency;Trusted_Connection=True;ConnectRetryCount=0",options => options.EnableRetryOnFailure());
}

如果其中一种内置策略不足以满足您的需求,则可以定义自己的策略并在那里处理异常:

这是自定义策略的示例:

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的一个服务器上运行,而数据库在AWS的另一台服务器上运行。

我的应用程序运行正常,但是弱2-3次,我收到了以下错误。

System.Data.Entity.Core.EntityException:基础提供程序在打开时失败。 ---> System.Data.SqlClient.SqlException:建立与SQL Server的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称正确,并且已将SQL Server配置为允许远程连接。 (提供者:命名管道提供程序,错误: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;
    }
}