Pet*_*ter 0 c# linq lambda entity-framework-core .net-core
我正在尝试针对实体框架核心2.0 DbContext在Linq中实现左外部联接。将查询转换为SQL,而不是在本地进行评估,这一点很重要。我已经查看了几种StackOverflow解决方案,其中包括一个不错的解决方案,但是没有一个使用EF Core。
我得到的问题是EF Core为该DefaultIfEmpty()方法返回以下警告/错误:
The LINQ expression 'DefaultIfEmpty()' could not be translated and will be evaluated locally
如果没有该DefaultIfEmpty()方法,则使用INNER JOIN。我的LINQ查询看起来像这样:
var join = context.Portfolios
.Where(p => p.IsActive)
.GroupJoin(context.BankAccounts,
prt => prt.Id,
bnk => bnk.PortfolioId,
(prt, bnks) => new {Portfolio=prt,Account=bnks.DefaultIfEmpty()})
.SelectMany(r => r.Accounts.DefaultIfEmpty(),
(p, b) => new
{
Id = p.Portfolio.Id,
BankAccount = b.BankAccountNumber,
BankRef = b.BeneficiaryReference,
Code = p.Portfolio.Code,
Description = p.Portfolio.DisplayName
});
Run Code Online (Sandbox Code Playgroud)
有谁知道解决这个问题的方法吗?
好的,这是我的错误,基于另一个SO问题的注释,该注释指出DefaultIfEmpty()了使查询成为OUTER JOIN所必需的。查看基础SQL,当我删除规范时,正在向数据库提交 LEFT JOIN DefaultIfEmpty()。我不确定这是否不同于对内存中集合进行LEFT JOIN,但这已经解决了我的问题。
EF Core为该Linq查询生成的SQL如下所示:
SELECT [p].[ID],
[bnk].[BankAccountNumber] AS [BankAccount],
[bnk].[BeneficiaryReference] AS [BankRef],
[p].[Code],
[p].[DisplayName] AS [Description]
FROM [Portfolio] AS [p]
LEFT JOIN [BankAccount] AS [bnk] ON [p].[ID] = [bnk].[PortfolioId]
WHERE (([p].[IsActive] = 1)))
Run Code Online (Sandbox Code Playgroud)
编辑:找到时间进行测试,@ Ivan Stoev是正确的:如果在EF上下文定义中正确设置了导航属性,则EF将生成LEFT JOIN。 使用EF时,这是一种更好的方法。
投资组合上的EF导航属性:
public virtual ICollection<BankAccount> BankAccounts { get; set; }
Run Code Online (Sandbox Code Playgroud)
通过导航属性进行LINQ查询:
var join = context.Portfolios
.Where(p => p.IsActive)
.SelectMany(p => p.BankAccounts.DefaultIfEmpty(), (p, b) => new
{
Id = p.Id,
BankAccount = b.BankAccountNumber,
BankRef = b.BeneficiaryReference,
Code = p.Code,
Description = p.DisplayName
});
Run Code Online (Sandbox Code Playgroud)
产生的SQL代码:
SELECT [p].[ID], [p.BankAccounts].[BankAccountNumber] AS [BankAccount], [p.BankAccounts].[BeneficiaryReference] AS [BankRef], [p].[Code], [p].[DisplayName] AS [Description]
FROM [core].[Portfolio] AS [p]
LEFT JOIN [ims].[BankAccount] AS [p.BankAccounts] ON [p].[ID] = [p.BankAccounts].[PortfolioId]
WHERE (([p].[IsActive] = 1))
Run Code Online (Sandbox Code Playgroud)
请注意,DefaultIfEmpty()从LINQ查询中删除会导致INNER JOIN。
| 归档时间: |
|
| 查看次数: |
4505 次 |
| 最近记录: |