在 Entity Framework Core 中执行子查询

gin*_*93r 3 entity-framework-core

我正在尝试使用 EF Core 将我们使用的一些常见查询转换为 API 调用,但我似乎无法让它工作。

通常运行的 SQL 看起来像这样:

select * 
from my_table 
where convert(date, datefield) = (select date 
                                  from another_table 
                                  where name == 'my_string')
Run Code Online (Sandbox Code Playgroud)

我尝试将其转换为 Linq 但没有结果。我尝试过类似的方法和类似的变体。

public async Task<my_table> GetStuff()
{
    return await _context.my_table
                         .Where(m => _context.another_table
                                             .Where(a => a.name == "my_string")
                                             .Select(a => a.date).Equals(m.updatedate)).FirstAsync();
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

System.InvalidOperationException: The LINQ expression 'DbSet<my_table>()
    .Where(t => DbSet<another_table>()
        .Where(t0 => t0.name == "my_string")
        .Select(t0 => t0.date).Equals((object)t.updatedate))' could not be translated.
Run Code Online (Sandbox Code Playgroud)

我看过一些关于使用Include或加入的帖子,但这些表不相关。

任何帮助,将不胜感激。谢谢!

Iva*_*oev 9

首先要提到的是,即使 SQL 也允许以下操作

where convert(date, datefield) = (select date 
                                  from another_table 
                                  where name == 'my_string')
Run Code Online (Sandbox Code Playgroud)

如果右子查询返回多个结果,它将失败。因为一般来说子查询(LINQ“集合”也是如此)返回序列,而不是单个值。

因此,更安全、更好的方法是使用IN

where convert(date, datefield) in (select date 
                                  from another_table 
                                  where name == 'my_string')
Run Code Online (Sandbox Code Playgroud)

或者EXISTS

where exists (select * from another_table 
    where name == 'my_string' and date == convert(date, my_table.datefield))
Run Code Online (Sandbox Code Playgroud)

这两个都自然地转化为 LINQ -INContains

_context.my_table
    .Where(m => _context.another_table
        .Where(a => a.name == "my_string")
        .Select(a => a.date)
        .Contains(m.updatedate) // <--
    )
Run Code Online (Sandbox Code Playgroud)

EXISTSAny

_context.my_table
    .Where(m => _context.another_table
        .Any(a => a.name == "my_string" && a.date == m.updatedate) // <--
    )
Run Code Online (Sandbox Code Playgroud)