Async LINQ запрашивает null при использовании Entity Framework 6 с Azure SQL?
У меня есть веб-приложение, которое я недавно переместил в Azure. В нем у меня есть довольно много запросов, которые используют async LINQ расширения EF (примеры ниже). Однако после миграции в Azure я заметил, что не только некоторые из этих запросов возвращают null
, но MiniProfiler даже не регистрирует их:
// returns null. No queries logged in MiniProfiler
var someUser = await context.Users.FirstOrDefaultAsync(x => x.Id == id)
// works 100% as expected
var someUser = context.Users.FirstOrDefault(x => x.Id == id)
Я также пытался "обмануть" его, позвонив .ToListAsync().FirstOrDefault()
. Конечно, это тоже не сработало.
Для чего это стоит, это приложение использует .NET 4.5 и EF6. Он также был запущен в традиционно размещенной производственной среде в течение ~18 месяцев.
Я уверен, что на этот вопрос где-то был дан ответ, но мне было трудно найти какую-либо информацию о нем.EDIT: id
в приведенном выше примере фактически происходит из отдельного метода, который получает текущий идентификатор пользователя от текущего участника:
// .GetUserId() is an extension method to get the userid from the principal
// Works with SQL Server
// Does not work with Azure SQL
var someUser = await context.Users.FirstOrDefaultAsync(x => x.Id == HttpContext.Current.GetUserId());
Чтобы исправить это, я вытащил этот вызов:
var userId = HttpContext.Current.GetUserId();
var someUser = await context.Users.FirstOrDefaultAsync(x => x.Id == userId);
Тем не менее, кто-нибудь знает почему это работает с традиционный SQL-сервер, но не при подключении к базе данных SQL Azure?
2 ответа:
При выполнении асинхронного кода EF6 использует
.ConfigureAwait(false)
для предотвращения взаимоблокировок, поэтому продолжение (тело метода после ожидания) больше не гарантирует выполнение того же потока.При запуске на локальном SQL-сервере время блокировки потока обычно ниже некоторого порогового значения, и поэтому продолжение выполняется синхронно, чтобы избежать переключения контекста. Однако SQL Azure имеет большую задержку и запускает правильное асинхронное выполнение, что приводит к потере контекста в этом случае. дело.
ASP.NET только устанавливает
HttpContext.Current
в потоке запроса, поэтому, когда EF вычисляет лямбда-код в потоке пула потоков, он будет равен null.
Вы пробовали поставить "ToListAsync" в конце запроса? Я полагаю, что неисправность может быть там из-за LINQ отложенного выполнения