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;
专家
我 运行 在访问我的 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;