配置弹性设置Entity Framework 6.02

时间:2014-01-31 15:29:18

标签: c# sql .net database entity-framework

我正在尝试为EF6.02配置弹性设置。我有一个应用程序,它在一个执行点将日志条目写入数据库。应用程序不依赖于SQL服务器,因此如果服务器没有响应,我希望应用程序放弃INSERT查询(通过DbContext的SaveChanges)并立即继续执行。

使用默认设置,调试日志输出十个

  

“System.Data.dll中出现'System.Data.SqlClient.SqlException'类型的第一次机会异常”

十次尝试后,它会抛出一个异常,我的代码会继续。但我想要一次尝试,例如2秒命令超时。根据MSDN上的文档,SQL Server的默认弹性方法是:

  

DefaultSqlExecutionStrategy 这是默认使用的内部执行策略。该策略根本不会重试,但它会包含任何可能是暂时的异常,以通知用户他们可能希望启用连接弹性。

正如文档所述,此策略根本不会重试。但我还有十次重试。我试图创建一个继承DbConfiguration的类,但我没有找到任何关于如何更改它的文档。

有人可以帮我减少重试次数吗?

更新:以下是基于建议的代码

using System;
using System.Data.Entity;
using System.Data.Entity.SqlServer;
using System.Data.Entity.Infrastructure;
using System.Runtime.Remoting.Messaging;

namespace MyDbLayer
{
    public class MyConfiguration : DbConfiguration
    {
        public MyConfiguration ()
        {

          this.SetExecutionStrategy("System.Data.SqlClient", () => SuspendExecutionStrategy
          ? (IDbExecutionStrategy)new DefaultExecutionStrategy()
          : new SqlAzureExecutionStrategy());
        }

        public static bool SuspendExecutionStrategy
        {
            get
            {
                return (bool?)CallContext.LogicalGetData("SuspendExecutionStrategy") ?? false;
            }
            set
            {
                CallContext.LogicalSetData("SuspendExecutionStrategy", value);
            }
        } 
    }
}

代码写入SQL

try
    {
        using (MyEntities context = new MyEntities ())
        {
            Log logEntry = new Log();
            logEntry.TS = DateTime.Now;

            MyConfiguration.SuspendExecutionStrategy = true;
            context.Log.Add(logEntry);
            context.SaveChanges();
        }
    }
    catch (Exception ex)
    {
        logger.Warn("Connection error with database server.", ex);
    }
    finally
    {
        //Enable retries again...
        MyConfiguration.SuspendExecutionStrategy = false;
    }

2 个答案:

答案 0 :(得分:6)

您是否尝试过execution strategy suspension

您自己的数据库配置就像这样:

public class MyConfiguration : DbConfiguration 
{ 
    public MyConfiguration() 
    { 
        this.SetExecutionStrategy("System.Data.SqlClient", () => SuspendExecutionStrategy 
          ? (IDbExecutionStrategy)new DefaultExecutionStrategy() 
          : new SqlAzureExecutionStrategy()); 
    } 

    public static bool SuspendExecutionStrategy 
    { 
        get 
        { 
            return (bool?)CallContext.LogicalGetData("SuspendExecutionStrategy") ?? false; 
        } 
        set 
        { 
            CallContext.LogicalSetData("SuspendExecutionStrategy", value); 
        } 
    } 
} 

然后您可以定义不可重复的命令:

public static void ExecWithoutRetry(System.Action action)
{
    var restoreExecutionStrategyState = EbgDbConfiguration.SuspendExecutionStrategy;
    try
    {
        MyConfiguration.SuspendExecutionStrategy = true;
        action();
    }
    catch (Exception)
    {
        // ignore any exception if we want to
    }
    finally
    {
        MyConfiguration.SuspendExecutionStrategy = restoreExecutionStrategyState;
    }
}

最后,具有可重复和不可重试命令的常规数据库代码可能如下所示:

using (var db = new MyContext())
{
    ExecWithoutRetry(() => db.WriteEvent("My event without retries"));
    db.DoAnyOperationWithRetryStrategy();
}

答案 1 :(得分:-1)

我找到了。我只需要添加“Connection Timeout = X”,其中X是连接字符串的秒数,一切正常,无需修改ExecutionStrategies等。

在执行查询之前添加它解决了它

contextInstance.Database.Connection.ConnectionString = context.Database.Connection.ConnectionString + ";Connection Timeout=2;";