【问题标题】:Async LINQ queries null when using Entity Framework 6 with Azure SQL?将 Entity Framework 6 与 Azure SQL 结合使用时,异步 LINQ 查询是否为空?
【发布时间】:2016-08-10 07:56:33
【问题描述】:

我有一个最近迁移到 Azure 的 Web 应用程序。在其中,我有很多使用 EF 的异步 LINQ 扩展的查询(下面的示例)。然而,自从迁移到 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 个月。

我确信这已经在某个地方得到了回答,但我一直很难找到有关它的任何信息。


编辑:上面示例中的id 实际上来自一个单独的方法,该方法从当前主体获取当前用户 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 Server,但在连接到 Azure SQL 数据库时却不行?

【问题讨论】:

  • 第一种方法,是不是整个调用栈都使用Async?
  • @ErikPhilips 是的,在这种情况下,整个调用堆栈都是异步的。它来自异步 MVC 操作
  • @valverij - 在该方法的任何地方或对该请求中的其他方法的调用中是否有任何Task<T>.Result 调用?您是否尝试过使方法尽可能简单,除了 mvc Action 主体中的return await context.Users.ToListAsync();
  • @Igor 哇,我现在感觉很笨。因此,那里的 id 实际上 来自 HttpContext,它在从异步查询中调用时返回 null。我注意到这种情况偶尔会发生(我知道为什么会发生),并且会定期将其取出。以前在使用 SQL Server 时不会发生这种情况。您知道 Azure SQL 为何如此吗?仅仅是底层 EF SQL 提供程序的不同吗?
  • @valverij - 不确定,但显然 http 上下文没有传递到 Sql Azure 正在执行的异步调用,可能是因为它也使用 http 进行连接?

标签: c# entity-framework azure async-await azure-sql-database


【解决方案1】:

EF6在执行异步代码时使用.ConfigureAwait(false)来防止死锁,因此不再保证继续(await之后的方法体)执行同一个线程。

在本地 SQL Server 上运行时,线程被阻塞的时间通常低于某个阈值,因此同步执行继续以避免上下文切换。然而,SQL Azure 有更多的延迟并触发适当的异步执行,导致在这种情况下丢失上下文。

ASP.NET 仅在请求线程上设置HttpContext.Current,因此当 EF 在线程池线程上计算 lambda 时,它将为 null。

【讨论】:

  • 换句话说,在将其传递给 EF LINQ 之前将该 Id 存储在局部变量中
【解决方案2】:

您是否尝试将“ToListAsync”放在查询的末尾?我相信故障可能是因为LINQ deferred execution

【讨论】:

  • 看看这个问题,是的,我试过了。此外,FirstOrDefault 与 ToList 非常相似,强制执行,因此延迟执行在这里不是问题
猜你喜欢
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多