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 2

2 ответа:

При выполнении асинхронного кода EF6 использует .ConfigureAwait(false) для предотвращения взаимоблокировок, поэтому продолжение (тело метода после ожидания) больше не гарантирует выполнение того же потока.

При запуске на локальном SQL-сервере время блокировки потока обычно ниже некоторого порогового значения, и поэтому продолжение выполняется синхронно, чтобы избежать переключения контекста. Однако SQL Azure имеет большую задержку и запускает правильное асинхронное выполнение, что приводит к потере контекста в этом случае. дело.

ASP.NET только устанавливает HttpContext.Current в потоке запроса, поэтому, когда EF вычисляет лямбда-код в потоке пула потоков, он будет равен null.

Вы пробовали поставить "ToListAsync" в конце запроса? Я полагаю, что неисправность может быть там из-за LINQ отложенного выполнения