如何在 .NET Core 3 中使用 LINQ 语法查询多个表

How to query multiple tables using LINQ syntax in .NET core 3

我需要查询两个数据库表以获取搜索词和 return 结果。以下在 EF Core 2 中工作:

var SearchTerm = "hello";
IQueryable<TableA> q;
q = (from a in context.TableA
     join b in context.TableB on a equals b.A into leftjoin
     from c in leftjoin.DefaultIfEmpty()                     
     where c.Column1.Contains(SearchTerm)
        || a.Column1.Contains(SearchTerm)
        || a.Column2.Contains(SearchTerm)
     select a);

return q.Include(a => a.TableD)
        .GroupBy(a => a.Id)
        .Select(group => group.First())
        .ToList();

上面的想法是采用 SearchTerm 并从 TableA 查询两列,连接到 TableB 并查询该列中的一列,然后 select 来自 TableA 的不同值。

在 .NET 3 中,上面的代码抛出一个错误,指出它无法转换为 SQL。我试着重写这个,我能做的最好的是:

var SearchTerm = "hello";
var q = (from a in context.TableA
         join b in context.TableB on a equals b.A into leftjoin
         from c in leftjoin.DefaultIfEmpty()                     
         where c.Column1.Contains(SearchTerm)
             || a.Column1.Contains(SearchTerm)
             || a.Column2.Contains(SearchTerm)                    
         select a.Id).Distinct().ToList();  

return context.TableA
    .Where(a => q.Contains(a.Id))
    .Include(c => c.TableD)
    .ToList();

它工作正常,但涉及两个数据库查询,因为我已经从第一个查询中获得了 TableA 的列表,如果能够只使用它而不必提取 ID 并执行第二个查询,那就太好了。另外确保数据库继续处理不同的部分而不是 C# 也是更可取的。

A和B的定义是:

public class TableA
{
    public int Id { get; set; }

    public string Column1 { get; set; }

    public string Column2 { get; set; }

    public int TableDId { get; set; }

    public TableD TableD { get; set; }
}

public class TableB
{
    public int Id { get; set; }

    public string Column1 { get; set; }

    public int TableAId { get; set; }

    public TableA TableA { get; set; }
}

如果我理解正确的话,你在 TableATableB 之间有一对多的关系,所以应该可以将集合导航 属性 添加到 TableA ] 例如 this tutorial

public class TableA
{
    public int Id { get; set; }
    ...
    public ICollection<TableB> TableBs { get; set; } 
}

所以你可以尝试做这样的事情:

context.TableA
    .Where(ta => ta.TableBs.Any(tb => tb.Column1.Contains(SearchTerm)) 
        || ta.Column1.Contains(SearchTerm) 
        || ta.Column2.Contains(SearchTerm))
    .Include(c => c.TableD)
    .ToList();

另一种选择是尝试子查询:

var q = (from a in context.TableA
         join b in context.TableB on a.Id equals b.TableAId  into leftjoin
         from c in leftjoin.DefaultIfEmpty()                     
         where c.Column1.Contains(SearchTerm)
             || a.Column1.Contains(SearchTerm)
             || a.Column2.Contains(SearchTerm)                    
         select a.Id);  // remove Distinct and ToList

return context.TableA
    .Where(a => q.Contains(a.Id))
    .Include(c => c.TableD)
    .ToList();