Entity Framework Core“未将对象引用设置为对象的实例”,并在 LINQ 中使用嵌套的 .Any

问题描述 投票:0回答:1

我有一个使用 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”来过滤结果。

看起来为null的具体对象是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 为 null):

                         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)

c# linq asp.net-core-mvc entity-framework-core asp.net-core-1.0
1个回答
0
投票

我的查询中有一个非常愚蠢的错误。

1.TryCreateFromCurrentValues(InternalEntityEntry entry, TKey& key) at Microsoft.EntityFrameworkCore.Query.Internal.WeakReferenceIdentityMap

我正在访问当前项目的 ItemDataUserRoles,但是,然后我将项目的 ItemDataUserRoles 列表过滤为仅与我的项目匹配的项目。显然,这是完全多余的检查。然而,这并没有打破它。破坏它的是我做的下一件事是检查这些 ItemDataUserRoles 是否与原始 ItemData 行上的用户匹配,而不是与传入的用户匹配。这会创建一个奇怪的 SQL 查询,并给出错误的结果。

© www.soinside.com 2019 - 2024. All rights reserved.