c# - Ef 返回 null,但实体存在
问题描述
我正在尝试在代码中加载一些用户信息,但 EF 返回 null。
foreach (var user in allAutoUsers)
{
Wallet wallet = db.CabinetUsers
.Find(user.IdCabinetUser)?
.Wallets
.FirstOrDefault(x => x.TypeCurrency == currency);
}
可变用户报告 1 个钱包,但是当我尝试在上面的代码中获取它时,它返回 null。
有一些方法可以解决这个问题吗?
解决方案
更多地阅读 Linq 表达式,而不是依赖Find
. 如果您的实体之间的关系未定义为virtual
阻止 EF 延迟加载它们,您可能会遇到问题。
using 的问题.Find()
是,如果实体存在,它将返回实体,但是,尝试访问 DbContext 尚未意识到的任何相关属性将需要延迟加载调用。如果延迟加载被禁用,或者成员不是,这很容易被忽略virtual
,并且在启用它时可能是性能问题。
相反,Linq 可以让您直接通过对象图进行查询以获得您想要的:
foreach (var user in allAutoUsers)
{
Wallet wallet = db.CabinetUsers
.Where(x => x.IdCabinetUser == user.IdCabinetUser)
.SelectMany(x => x.Wallets)
.SingleOrDefault(x => x.TypeCurrency == currency);
// do stuff with wallet...
}
这假设每个用户只有 1 个指定货币的钱包。当期望 0 或 1 时,使用SingleOrDefault
. FirstOrDefault
仅在您期望 0 或多个、想要“第一个”并指定一个OrderBy
子句以确保第一个项目是可预测的时使用。
这将导致每个用户的查询。为所有用户完成 1 个查询:
var userIds = allAutoUsers.Select(x => x.IdCabinetUser).ToList();
var userWallets = db.CabinetUsers
.Where(x => userIds.Contains(x.IdCabinetUser))
.Select(x => new
{
x.IdCabinetUser,
Wallet = x.SelectMany(x => x.Wallets)
.SingleOrDefault(x => x.TypeCurrency == currency);
}).ToList();
从这里我会考虑用你真正关心的钱包中的细节来扩展钱包SelectMany
,Select
而不是引用整个钱包实体。这样做的好处是可以加快查询速度,减少内存使用,并避免在 Wallet 引用稍后涉及的任何其他实体时延迟加载调用导致问题发生的可能性。
例如,如果您只需要 IdWallet、WalletName、TypeCurrency 和 Balance:
// replace this line from above...
Wallet = x.SelectMany(x => x.Wallets)
// with ...
Wallet = x.SelectMany(x => x.Wallets.Select(w => new
{
w.IdWallet,
w.WalletName,
w.TypeCurrency,
w.Ballance
}) // ...
从那里您foreach
无需额外查询即可满足您的需求:
foreach ( var userWallet in userWallets)
{
// do stuff with userWallet.Wallet and userWallet.IdCabinetUser.
}
如果您想将钱包详细信息返回给调用方法或视图等,那么您不能为此使用匿名类型(new { }
)。相反,您需要为要返回和使用的数据定义一个简单的类Select
。即new WalletDTO { IdWallet = w.IdWallet, //... }
即使您使用实体,也建议将它们减少为 DTO 或 ViewModel,而不是返回实体。实体不应该比产生它们的 DbContext “存活”更长的时间,否则你会得到各种讨厌的行为,比如ObjectDisposedException
和序列化异常。
推荐阅读
- javascript - 在网站上显示当地天气和时间
- wso2 - API 3.1.0 和 BPS (EI 6.6.0) 中的用户注册工作流程
- java - Java Buffered Reader 的 readline() 读取结果为 null 是怎么回事?
- swiftui - 在 SwiftUI 中声明这么多函数是否可取?
- angular - 在数据排序条形图中的条形图中添加动画 Highcharts
- python - VSCode、Python 新手 - 一些环境问题
- python - Xgboost 参数 scale_pos_weight 用于代价敏感的学习
- ios - XCode 11.3 崩溃,iOS 13.2.2 模拟器 iPhone X 和 watchOS 4.2 Apple Watch 42mm
- asp.net-mvc - MVC-需要帮助来创建“编辑”视图
- angular - 如何在 Angular 动态加载组件中使用管道?