简体   繁体   English

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

[英]How to catch exception when database connection is lost when using EF?

I'm using ADO.NET Entity Data Model EF Designer from the database.我正在使用数据库中的 ADO.NET 实体数据 Model EF Designer。 My SQL server is on another PC and when I lost connection with the database my app stops and I can only shut it down.我的 SQL 服务器在另一台 PC 上,当我失去与数据库的连接时,我的应用程序停止了,我只能将其关闭。 I get:我得到:

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

Is there any way to solve this problem?有什么办法可以解决这个问题吗?

For both resiliency and custom handling, the answer is the same.对于弹性和自定义处理,答案是相同的。 You need to configure a strategy:你需要配置一个策略:

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

The following code, enables retrying on failure:以下代码启用失败重试:

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

If one of the built in strategies is not enough for you, you can define your own and handle the exception there:如果其中一种内置策略对您来说不够用,您可以定义自己的策略并在那里处理异常:

This is an example of custom strategies:这是自定义策略的示例:

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();   
}

My Application is running on the one server and database is running on the another server in the AWS.我的应用程序在一台服务器上运行,数据库在 AWS 的另一台服务器上运行。

My application is working smoothly, But 2-3 times weakly I got the error like the below.我的应用程序运行顺利,但是有 2-3 次我收到如下错误。

System.Data.Entity.Core.EntityException: The underlying provider failed on Open. System.Data.Entity.Core.EntityException:基础提供程序在打开时失败。 ---> System.Data.SqlClient.SqlException: A.network-related or instance-specific error occurred while establishing a connection to SQL Server. ---> System.Data.SqlClient.SqlException:建立与 SQL 服务器的连接时发生与网络相关或特定于实例的错误。 The server was not found or was not accessible.服务器未找到或无法访问。 Verify that the instance name is correct and that SQL Server is configured to allow remote connections.验证实例名称是否正确以及 SQL 服务器是否配置为允许远程连接。 (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception: Access is denied In first request I got the above error and after the immediate another request I does not get any error and request is successful. (提供程序:命名管道提供程序,错误:40 - 无法打开与 SQL 服务器的连接)---> System.ComponentModel.Win32Exception:访问被拒绝得到任何错误并且请求成功。

After doing some Google I got the concept like the Connection Resiliency I implemented in my application and it works and retry the query for some specific times after some specific period.在做了一些谷歌之后,我得到了像我在我的应用程序中实现的连接弹性这样的概念,它可以工作并在特定时间段后的特定时间重试查询。

But it fails in the case of the where I used my Custom Transactions like in the above code.但是在我使用上面代码中的自定义事务的情况下,它失败了。 It throws the error like this.它抛出这样的错误。

System.InvalidOperationException: The configured execution strategy 'MYExecutionStrategy' does not support user initiated transactions. System.InvalidOperationException:配置的执行策略“MYExecutionStrategy”不支持用户启动的事务。 See http://go.microsoft.com/fwlink/?LinkId=309381 for additional information.有关其他信息,请参阅http://go.microsoft.com/fwlink/?LinkId=309381 I configured the Execution Strategy like this:我这样配置执行策略:

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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM