【问题标题】:Entity Framework Core "Object reference not set to an instance of an object" with nested .Any in LINQ实体框架核心“对象引用未设置为对象的实例”,在 LINQ 中具有嵌套的 .Any
【发布时间】: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 =&gt; r.UserRoleId != null &amp;&amp; t.RoleId == r.UserRoleId )
  • 或尝试使用两个单独的语句而不是一个长语句....
  • 我的第一个幸运猜测是 Roles 为空,所以如果你先做一个空检查。
  • 同意作为单个语句的查询似乎相当复杂......但是......实际错误在 s.Item.ItemName......所以这可能是一些ItemData没有Item 或一些Itemnull ItemName ...尝试给这个( string.IsNullOrEmpty( itemName ) || ( (s.Item != null) &amp;&amp; (s.Item.ItemName != null) &amp;&amp; (s.Item.ItemName.ToLower() == itemName.ToLower()) ) ) 带来麻烦的行

标签: c# linq asp.net-core-mvc entity-framework-core asp.net-core-1.0


【解决方案1】:

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

              s.ItemDataUserRoles.Any( r => r.ItemDataId == s.Id &&
              s.User.Roles.Any( t => t.RoleId == r.UserRoleId ) ) ) &&

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

【讨论】:

    猜你喜欢
    • 2022-01-08
    • 2018-04-02
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多