.net - Linq Select 不会在 EF Core 中检索超过 3 个子级别的对象数据
问题描述
在有人质疑我对这个数据库的商业案例的奇怪之处之前,我已经用虚构的对象名称替换了对象名称 :)
如果我将下面代码中的 FavouriteBook.Name 替换为 FavouriteBookId.ToString() 我会得到很好的恢复,因为如果有用户,总会有一本最喜欢的书。如果商店没有用户,以下代码也适用。但是一旦有用户.. 如果数据比 Profile 更深,它似乎不想获取数据。
(个人资料是用户的强制对象,喜欢的书是个人资料的强制对象。“名称”是FavouriteBook对象上的字符串属性)
var ret = _context.Shops.Where(x => x.ShopId == shopId);
var selected= ret.Select(y => new UserSummaryRow //my DTO
{
//…other properties being set have been trimmed
UserFavouriteBook =
y.User.FirstOrDefault(x => x.UserId == y.UserId) == null ? "N/A"
: y.User.FirstOrDefault(x => x.UserId == y.UserId).Profile.FavouriteBook.Name
});
var summary = await selected.ToListAsync();
return summary;
当执行带有“await”的行时,调用此存储库方法的 api 方法返回错误请求并显示错误:
- $exception {System.NullReferenceException:对象引用未设置为对象的实例。在 Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.TaskLiftingExpressionVisitor 的 lambda_method(Closure, Object[])。Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.AsyncSelectEnumerable 处的ExecuteAsync[T](IReadOnlyList
1 taskFactories, Func
2 选择器)2.AsyncSelectEnumerator.MoveNext(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor
System.Linq.AsyncEnumerable.Aggregate 处的 1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancelToken) [TSource,TAccumulate,TResult](IAsyncEnumerable1 source, TAccumulate seed, Func
3 累加器, Func2 resultSelector, CancellationToken cancellationToken) at {namespace of repo method}(Int32 RecId, List
1 statuses) in .cs:line 2104 at {namespace on api controller method}(String dtoString) in C:\Dev}path to repo}:line 608} System.NullReferenceException
输出显示:
Microsoft.EntityFrameworkCore.Query:Error:在迭代上下文类型“{我的上下文的命名空间}”的查询结果时,数据库中发生异常。System.NullReferenceException:对象引用未设置为对象的实例。
1 taskFactories, Func
在Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.AsyncSelectEnumerable2.AsyncSelectEnumerator.MoveNext(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor
1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancelToken )的 lambda_method(Closure , Object[] )
我正在使用 .NET Core / EF Core / SQL Server 13.0。
解决方案
我不能确切地说出问题所在,因为它取决于使用的 EF Core 版本 - EF Core 查询翻译/处理仍然不稳定。如果您包含 EF Core 日志记录输出(如执行的 SQL 查询、客户端评估警告(如果有)等),那就太好了。
但一般来说像这样的表达
y.User.FirstOrDefault(x => x.UserId == y.UserId).Profile.FavouriteBook.Name
总是可疑的——正确的执行完全取决于查询提供者对null
由FirstOrDefault
. LINQ to Objects 肯定会抛出 NRE。如果使用服务器评估,EF Core 应该能够通过返回来处理它null
,但根据异常,它不是由于翻译或客户端/混合结果评估。
话虽如此,我个人会尝试使用等效的“自然”方式返回null
最终值,方法是使用包含最终属性的Where
+然后应用,例如Select
FirstOrDefault
UserFavouriteBook = y.User
.Where(x => x.UserId == y.UserId)
.Select(x => x.Profile.FavouriteBook.Name)
.FirstOrDefault() ?? "N/A"
推荐阅读
- c# - 按下火空格键时会播放 AudioSource?
- python - 使用python提取回归系数
- html - 最好的 flexbox 包装器/图像配置是什么?
- .htaccess - 正确 .htaccess 将所有 https:// 页面重定向到 https://www
- javascript - 如何使删除按钮和完成按钮在 ToDO List Javascript 上工作
- python - 在 Virtualenv 中的 Pip 安装工作,但 * 不 * 使用 `-r requirements.txt`
- google-apps-script - 使用可安装的 onedit 触发器从共享的谷歌表调用 showModalDialog
- android - 使用改造处理错误
- typescript - TS2554 预期 1 个参数,但 HTMLImageElement onerror() 为 0
- android - 如果没有 @Inject 构造函数或 @Provides-annotated 方法,则无法提供片段