我正在尝试为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;
}
答案 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;";