【发布时间】:2016-11-13 23:39:03
【问题描述】:
我有一个使用 Entity Framework Core 1.0.0 的 ASP.NET Core 应用程序。
在特定查询中,我收到“未设置对象实例的对象引用”异常。
导致异常的查询是:
return mContext.ItemDatas
.Include( a => a.ItemDataUserRoles )
.Include( b => b.Item )
.Include( c => c.User ).ThenInclude( d => d.Roles )
.Where(
s =>
( s.User.Id == user.Id ||
s.ItemDataUserRoles.Any( r => r.ItemDataId == s.Id &&
s.User.Roles.Any( t => t.RoleId == r.UserRoleId ) ) ) &&
( string.IsNullOrEmpty( id ) || s.Id == id ) &&
( string.IsNullOrEmpty( itemName ) || s.Item.ItemName.ToLower() == itemName.ToLower() ) &&
s.IsActive );
查询的目标是返回一个完全填充的 ItemData 对象,其中项目属于用户或属于用户所属的任何角色。 ItemData 表有一个指向 User 的外键,表示它属于哪个用户。还有一个 ItemDataUserRoles 表,用于跟踪 ItemData 和 UserRole 之间的多对多关系。
查询的其余部分是根据可以传递给方法的可选“id”和“itemName”过滤结果。
看起来为空的特定对象是 s.Item。如果我将“s.Item.ItemName.ToLower()”更改为 s.ItemId.ToLower(),它可以正常工作。
然而,真正的罪魁祸首似乎是:
s.ItemDataUserRoles.Any( r => r.ItemDataId == s.Id &&
s.User.Roles.Any( t => t.RoleId == r.UserRoleId ) ) ) &&
如果我删除“s.User.Roles.Any”部分,它可以正常工作(但不会给我所需的结果)。显然,我可以进行单独的查询来获取用户角色数据并进行交叉检查,但是在像这样手动将其分开之前,我想确保我没有遗漏一些愚蠢的东西。我花了很多时间试图弄清楚我的大脑是怎么回事。
还值得注意的是,如果我删除了对 id 和 itemName 的过滤,则查询工作正常,并且似乎正确返回了属于用户或用户所属角色的项目。
下面是堆栈跟踪(InnerException 为空):
at lambda_method(Closure , InternalEntityEntry )
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SimpleFullyNullableDependentKeyValueFactory1.TryCreateFromCurrentValues(InternalEntityEntry entry, TKey& key)
at Microsoft.EntityFrameworkCore.Query.Internal.WeakReferenceIdentityMap1.CreateIncludeKeyComparer(INavigation navigation, InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.IncludeCore(Object entity, INavigation navigation)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext, Object entity, IReadOnlyList1 navigationPath, IReadOnlyList1 relatedEntitiesLoaders, Int32 currentNavigationIndex, Boolean queryStateManager)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext, Object entity, IReadOnlyList1 navigationPath, IReadOnlyList1 relatedEntitiesLoaders, Boolean queryStateManager)
at Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(Object entity)
at Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(Object entity)
at Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(Object entity)
at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.<_GroupJoin>d__264.MoveNext()
at System.Linq.Enumerable.<SelectManyIterator>d__1633.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__152.MoveNext()
at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
at Web.ItemHandlers.GenericItemHandler`1.Get(DataContract dataContract, UserAccount user, ItemDbContext dbc)
at Web.Controllers.ItemDataController.Get(String item)
【问题讨论】:
-
您是否尝试检查您的 lambda 表达式中的空值?例如:
s.User.Roles.Any( t => r.UserRoleId != null && t.RoleId == r.UserRoleId ) -
或尝试使用两个单独的语句而不是一个长语句....
-
我的第一个幸运猜测是 Roles 为空,所以如果你先做一个空检查。
-
同意作为单个语句的查询似乎相当复杂......但是......实际错误在 s.Item.ItemName......所以这可能是一些
ItemData没有Item或一些Item有nullItemName...尝试给这个( string.IsNullOrEmpty( itemName ) || ( (s.Item != null) && (s.Item.ItemName != null) && (s.Item.ItemName.ToLower() == itemName.ToLower()) ) )带来麻烦的行
标签: c# linq asp.net-core-mvc entity-framework-core asp.net-core-1.0