Множественные результирующие наборы Entity Framework, устойчивость Azure Connection и перехват команд
Я пытаюсь добавить устойчивость соединения к своему классу репозитория и протестировать его, чтобы переместить мою службу WCF в Azure. У Джули Лерман есть отличный пост:
http://thedatafarm.com/data-access/testing-out-the-connection-resiliency-feature-into-ef6/
Когда я вызываю метод репозитория, который использует обычные запросы Entity Framework, срабатывает метод Interceptor ReaderExecuting, и я могу смоделировать проблему с соединением.
var states = dbContext.Blogs.ToList();
Но по какой-то причине метод Interceptor ReaderExecuting не вызывается, когда выполняется один из моих методов репозитория, который использует "множественные результирующие наборы", возвращенные из хранимой процедуры (см. Код ниже). Я ожидаю, что метод ReaderExecuting вызывается при выполнении "ObjectContext.Translate" или "ToList", но это не так:
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 для обработки временных исключений.
Вы когда-нибудь сталкивались с этой ситуацией?
У вас есть какое-то решение для этого?
3 ответа
Из-за ограничения EF, упомянутого @tdykstra, я изменил свой хранимый процесс, чтобы он возвращал вывод XML вместо "множественных результирующих наборов". Я использовал метод SqlQuery для вызова хранимой процедуры и получения выходного XML, а затем десериализовал XML в объекты. Таким образом, метод Interceptor ReaderExecuting был выполнен, и я смог проверить устойчивость соединения. Надеемся, что команда EF добавит больше поддержки "множественных наборов результатов" в будущих выпусках. Вот пример кода:
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>();
В этом сценарии вызов ExecuteReader выходит за рамки EF - код вызывает его непосредственно в объекте команды ADO.NET. Поскольку вы полностью обходите EF для выполнения команды, вы пропускаете все EF (включая перехватчики). Translate просто берет уже полученные результаты и заполняет их в объекты.
Вы пробовали подключить встроенную отказоустойчивость соединения из пользовательских 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, и у меня не было проблем с ним.