ASP.NET MVC 5 中 EntityFramework 中的意外底层 NullReferenceException 问题

Accidentally underlying NullReferenceException issue in EntityFramework in ASP.NET MVC 5

专家

我 运行 在访问我的 MVC 5 网站的主页时遇到了麻烦,请参阅下面的异常详细信息。

MVC 5.2.2

EntityFramework6.1.1

Visual Studio 2013

System.NullReferenceException: Object reference not set to an instance of an object.
at System.Data.Entity.Core.Objects.ELinq.QueryParameterExpression.TryGetFieldOrPropertyValue(MemberExpression me, Object instance, Object& memberValue)
at System.Data.Entity.Core.Objects.ELinq.QueryParameterExpression.TryEvaluatePath(Expression expression, ConstantExpression& constantExpression)
at System.Data.Entity.Core.Objects.ELinq.QueryParameterExpression.EvaluateParameter(Object[] arguments)
at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClassc.<GetResultsAsync>b__a()
at System.Data.Entity.Core.Objects.ObjectContext.<ExecuteInTransactionAsync>d__3d`1.MoveNext()

代码很简单,从当前OwinContext共享的数据上下文中异步查询数据,正常运行,但是一不小心,因为报错失败了以前。

public class TalentsService : ServiceBase
{
    public async Task<List<TalentSummaryViewModel>> GetSlotlightTalents()
    {
        var talents = await DbContext.Talents.Where(t => t.IsSpotlight && IsAuthenticated).ToListAsync();

        return talents.Select(t => WrapModel(t)).ToList();
    }
}

public abstract class ServiceBase
{
    private ApplicationDbContext _dbContext;
    public ApplicationDbContext DbContext
    {
        get
        {
            return _dbContext ?? HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>();
        }
        private set
        {
            _dbContext = value;
        }
    }

    public bool IsAuthenticated
    {
        get
        {
            return HttpContext.Current.Request.IsAuthenticated;
        }
    }
}

那个跟多线程有关吗?我无法弄清楚根本原因是什么,任何线索将不胜感激,提前致谢。

感谢 Chris Pratt 的回复,这让我仔细检查了我的代码,根本原因是:

在我不知道的某些情况下 HttpContext.Current 为 null,然后对此 属性 IsAuthenticated 的调用失败,因此我必须将 IsAuthenticated 值存储在局部变量中,现在我可以在使用 LoadTest 工具启动大量请求时轻松重现这个问题,但仍然不清楚为什么上下文会意外丢失,可能其他人对此有更多了解。

在对我的 Web API 发出第一个 HTTP 请求后,我遇到了同样的错误,该错误只有在回收 IIS 应用程序时才能重现。显然,在重新启动 IIS 后,第一个传入请求是通过 IQueryable 启动数据检索,其中包含从以下位置提取的内联 ClientID 参数:

(HttpContext.Current.User 作为 ClaimsPrincipal)。以异步方式收集声明。

所以当 I/O 操作完成时——HttpRequest 上下文不存在... 将 Http Claim 值复制到单独的变量中并在构造 IQueryable 时使用此变量解决了问题:

var claims = (HttpContext.Current.User as ClaimsPrincipal).Claims;