LINQ查询无关联表报错:如何获取与银行账户匹配的支付记录
问题原因
- 原LINQ语句报错是因为EF Core无法翻译对内存集合
bankAccounts的多条件Any查询,且原查询逻辑本身存在缺陷:分开匹配账号和清算号的存在性,会出现不同账户的账号和清算号交叉命中的问题,不符合业务匹配要求。 - 之前配置表关联失败是因为
BankAccount表中存在AccountNumber或SortCode为null的记录,EF的替代键不允许字段为null,在没有修改数据库和数据权限的前提下,不适合用导航属性关联方案。
解决方案
最优方案:单次服务端查询(推荐)
直接将两个表的匹配逻辑合并为单次查询,完全由EF翻译成SQL在数据库端执行,无需提前加载银行账户到内存:
var payments = _databaseContext.Payments .Where(p => _databaseContext.BankAccounts // 筛选指定ID的银行账户 .Where(b => model.BankAccountIds.Contains(b.Id)) // 匹配账号+清算号的组合,存在符合项即命中 .Any(b => b.AccountNumber == p.AccountNumber && b.SortCode == p.SortCode)) .ToList();
如果需要匹配支付表6组账号/清算号中的任意一组,调整Any内的条件即可:
var payments = _databaseContext.Payments .Where(p => _databaseContext.BankAccounts .Where(b => model.BankAccountIds.Contains(b.Id)) .Any(b => (b.AccountNumber == p.AccountNumber1 && b.SortCode == p.SortCode1) || (b.AccountNumber == p.AccountNumber2 && b.SortCode == p.SortCode2) || (b.AccountNumber == p.AccountNumber3 && b.SortCode == p.SortCode3) || (b.AccountNumber == p.AccountNumber4 && b.SortCode == p.SortCode4) || (b.AccountNumber == p.AccountNumber5 && b.SortCode == p.SortCode5) || (b.AccountNumber == p.AccountNumber6 && b.SortCode == p.SortCode6) )) .ToList();
备选方案:提前加载银行账户复用
如果确实需要提前把筛选后的银行账户加载到内存复用,可将匹配键拼接为唯一字符串后用Contains查询,EF支持该方法的翻译:
// 提前加载指定ID银行账户的匹配键组合,分隔符||确保不会出现在账号、清算号的合法取值中即可 var bankAccountKeys = _databaseContext.BankAccounts .Where(b => model.BankAccountIds.Contains(b.Id)) .Select(b => $"{b.AccountNumber}||{b.SortCode}") .ToList(); // 查询匹配的支付记录 var payments = _databaseContext.Payments .Where(p => bankAccountKeys.Contains($"{p.AccountNumber1}||{p.SortCode1}") || bankAccountKeys.Contains($"{p.AccountNumber2}||{p.SortCode2}") // 补充剩余4组的判断即可 ) .ToList();
内容的提问来源于stack exchange,提问作者Simon Price
相关产品推荐
相关产品推荐

