Ada*_*ley 16 .net entity-framework enterprise-library
我目前在我的应用程序中使用SQL Azure和Entity SQL.
例如
Entities model = new Entities();
db_Item item = model.db_Item.First();
Run Code Online (Sandbox Code Playgroud)
现在我想在企业库中使用瞬态故障处理,但是没有我能找到的示例或解决方案可以让我做一些事情,比如覆盖Entities类,所以我不必更新数百个代码的地方.
有人可以提供更多关于如何做到这一点的信息吗?
Ada*_*ley 18
了解到目前为止我所拥有的.
实体框架不提供对连接打开的访问以及将SQL发送到服务器的部分,因此目前在该区域周围提供重试逻辑是不可能的.
EF团队意识到了这一不足,并计划将重试逻辑实际集成到EF中,以备可能的版本6.
根据[1]的案例#3,您可以在OnContextCreated上向数据库发送SQL命令.但这意味着,对于您对数据库进行的每次单独数据库调用,您都必须进行2.我不会在任何情况下推荐这种情况,除非您不关心性能.
到目前为止,唯一可行的选择是围绕您对数据库进行的每次调用,以企业库瞬态故障处理应用程序块[2]的形式实现重试逻辑.在现有的应用程序中,这非常繁琐.
当我有时间的时候,我正在进一步研究EF的源代码,看看是否还有其他事情可以做,而我们等待EF 6.我会关注[3]
有些人希望,目前EF团队正在审核.[4]
更新: 2013-11-14
我想我会更新这篇文章,让每个人都知道EF6已经发布并支持开箱即用的连接弹性.https://www.nuget.org/packages/EntityFramework/
不再需要解决方法了.
更新: 2013-03-23
EF 6 Alpha 3发布时带有连接弹性 - http://entityframework.codeplex.com/wikipage?title=Connection%20Resiliency%20Spec
更新: 2012-11-04
EF团队已正式宣布计划用于EF 6. [4]
[2] http://msdn.microsoft.com/en-us/library/hh680934(v=pandp.50).aspx
[3] http://entityframework.codeplex.com/wikipage?title=Roadmap
Jos*_*ith 11
值得庆幸的是,新的瞬态故障处理应用程序块非常简单.你需要的一切都可以在这里找到:
并以视频形式:
http://channel9.msdn.com/Shows/Cloud+Cover/Episode-68-Throttling-in-SQL-Azure-with-Scott-Klein
以上链接的一个例子:
using (NorthwindEntities dc = new NorthwindEntities())
{
RetryPolicy myPolicy = new RetryPolicy<SqlAzureTransientErrorDetectionStrategy>(3);
Employee e1 = myPolicy.ExecuteAction<Employee>(() =>
(from x in dc.Employees
where x.LastName == "King"
select x).First());
}
Run Code Online (Sandbox Code Playgroud)
如您所见,您需要做的就是创建一个RetryPolicy并使用包含在操作中的查询调用其ExecuteAction函数.
**编辑
示例上下文覆盖:
private RetryPolicy m_RetryPolicy = new RetryPolicy<SqlAzureTransientErrorDetectionStrategy>(....
public override int SaveChanges()
{
return m_RetryPolicy.ExecuteAction<int>(() =>
{
return base.SaveChanges();
});
}
// Pass anonymous query func in here
public T AutoRetryQuery<T>(Func<T> query)
{
return m_RetryPolicy.ExecuteAction<T>(query);
}
Run Code Online (Sandbox Code Playgroud)
O'R*_*ney 11
由于这似乎是有关Azure瞬态处理的最流行的问题之一,我将在此处添加此答案.
实体框架确实内置了弹性代码(根据Adam的回答)
但:
1)您必须手动添加代码以激活它
public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
this.SetExecutionStrategy(
"System.Data.SqlClient",
() => new SqlAzureExecutionStrategy());
this.SetTransactionHandler(
SqlProviderServices.ProviderInvariantName,
() => new CommitFailureHandler());
}
...
Run Code Online (Sandbox Code Playgroud)
第一个方法调用激活重试,第二个调用设置处理程序以避免重试发生时的重复更新.
注意:此类将自动找到并实例化,如下所述:https://msdn.microsoft.com/en-us/library/jj680699(v = vs133).aspx.只需确保该类与DbContext类位于同一个程序集中,并且具有不带参数的公共构造函数.
2)内置的SqlAzureExecutionStrategy 不够好.它不包括所有瞬态错误.当您考虑SQL Server团队独立于Entity Framework工作时,这并不奇怪,因此他们不太可能完全同步可能出现的瞬态错误.你自己也很难理解这一点.
我们使用的解决方案,由另一家软件公司的建议支持,是创建我们自己的执行策略,它重试每个 SqlException和TimeoutException,除了一些我们白名单不值得重试(例如权限被拒绝).
public class WhiteListSqlAzureExecutionStrategy : DbExecutionStrategy
{
public WhiteListSqlAzureExecutionStrategy()
{
}
protected override bool ShouldRetryOn(Exception exception)
{
var sqlException = exception as SqlException;
// If this is an SqlException then we want to always retry
// Unless the all the exception types are in the white list.
// With those errors there is no point in retrying.
if (sqlException != null)
{
var retry = false;
foreach (SqlError err in sqlException.Errors)
{
// Exception white list.
switch (err.Number)
{
// Primary Key violation
// https://msdn.microsoft.com/en-us/library/ms151757(v=sql.100).aspx
case 2627:
// Constraint violation
case 547:
// Invalid column name, We have seen this happen when the Snapshot helper runs for a column 'CreatedOn'
// This is not one of our columns and it appears to be using our execution strategy.
// An invalid column is also something that probably doesn't get resolved by retries.
case 207:
break;
// The server principal "username" is not able to access the database "dbname" under the current security context
// May occur when using restricted user - Entity Framework wants to access master for something
// probably not transient
case 916:
break;
// XXX permission denied on object. (XXX = select, etc)
// Should not occur if db access is correct, but occurred when using restricted user - EF accessing __MigrationHistory
case 229:
break;
// Invalid object name 'xxx'.
// Occurs at startup because Entity Framework looks for EdmMetadata, an old table
// (Perhaps only if it can't access __MigrationHistory?)
case 208:
break;
default:
retry = true;
break;
}
}
return retry;
}
if (exception is TimeoutException)
{
return true;
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
3)有一种错误,其中EF运行重试N ^ 2次而不是N,这使得延迟比你预期的要长得多.它应该需要大约26秒,但这个错误需要几分钟.但是,这并不是那么糟糕,因为实际上SQL Azure通常不会超过一分钟:( https://entityframework.codeplex.com/workitem/2849
4)如果你还没有这样做,你真的需要在使用后处理你的DbContext.似乎这就是CommitFailureHandler运行它清除整理__TransactionHistory表的点; 如果你不处理,这个表将永远增长(虽然见下一点).
5)您应该在启动时或后台线程中的某处调用ClearTransactionHistory,以清除__TransactionHistory中的任何剩余部分.