Entity Framework 多个结果集、Azure 连接弹性和命令拦截

Entity Framework Multiple Result Sets, Azure Connection Resiliency and Command Interception

我正在尝试将连接弹性添加到我的存储库 class 并对其进行测试,以便将我的 WCF 服务移动到 Azure。朱莉勒曼有一个很棒的post:

http://thedatafarm.com/data-access/testing-out-the-connection-resiliency-feature-into-ef6/#comment-61311

当我调用使用普通 Entity Framework 查询的存储库方法时,会触发 Interceptor ReaderExecuting 方法,我能够模拟连接问题。

var states = dbContext.Blogs.ToList();

但是由于某种原因,当我的其中一个使用从存储过程返回的“多个结果集”的存储库方法正在执行时,不会调用 Interceptor ReaderExecuting 方法(请参见下面的代码)。我期待在执行 "ObjectContext.Translate" 或 "ToList" 时调用 ReaderExecuting 方法,但它不会:

db.Database.Connection.Open();

var reader = cmd.ExecuteReader();

var blogs = ((IObjectContextAdapter)db).ObjectContext.Translate<Blog>(reader).ToList();

仅供参考,我正在关注这篇处理“多个结果集”的文章:

https://msdn.microsoft.com/en-us/data/jj691402.aspx

我正在尝试依靠 Entity Framework 6+ 执行策略来处理连接弹性。但是如果它不能处理多个结果集,我的下一个选择是使用 Polly 库来处理瞬态异常。

你曾经运行遇到过这种情况吗?

你有什么解决办法吗?

您是否尝试过像这样从自定义 DbConfiguration 实现中连接内置连接弹性?

public class MyDbConfiguration : DbConfiguration
{
    public MyDbConfiguration()
        : base()
    {
        var strategy = System.Data.Entity.SqlServer.SqlAzureExecutionStrategy();
        SetExecutionStrategy("System.Data.EntityClient", strategy);
        SetExecutionStrategy("System.Data.SqlClient", strategy);
    }
}

我在 MARS 中使用了这种方法,没有遇到任何问题。

在这种情况下,对 ExecuteReader 的调用超出了 EF 的范围 - 代码直接在 ADO.NET 命令对象上调用它。因为您完全绕过 EF 来执行命令,所以您会错过所有 EF(包括拦截器)。翻译只是获取已经检索到的结果并将它们填充到对象中。

由于@tdykstra 提到的 EF 限制,我将存储过程更改为 return 和 XML 输出而不是 "Multiple Result Sets"。我使用 "SqlQuery" 方法调用存储过程并获得输出 XML,然后我将 XML 反序列化为对象。这样 Interceptor ReaderExecuting 方法得到执行,我能够测试连接弹性。希望 EF 团队在未来的版本中添加对 "Multiple Result Sets" 的更多支持。 这是示例代码:

var paramId = new SqlParameter
{
    ParameterName = "id",
    SqlDbType = SqlDbType.Xml,
    Direction = ParameterDirection.Input,
    Value = 1
};

var paramXmlResult = new SqlParameter
{
    ParameterName = "XmlResult",
    SqlDbType = SqlDbType.Xml,
    Direction = ParameterDirection.Output
};

db.Database.SqlQuery<XElement>(
    "EXEC [dbo].[GetDataAsXml] @id, @XmlResult OUT", 
    paramId, paramXmlResult).ToList();


XElement xmlResult = XElement.Parse(paramXmlResult.Value.ToString());

//FromXElement is an Extension method that deserializes XML into a Type (like MyData)
MyData data = xmlResult.FromXElement<MyData>();