如何在 .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; }
}
如果我理解正确的话,你在 TableA
和 TableB
之间有一对多的关系,所以应该可以将集合导航 属性 添加到 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();
我需要查询两个数据库表以获取搜索词和 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; }
}
如果我理解正确的话,你在 TableA
和 TableB
之间有一对多的关系,所以应该可以将集合导航 属性 添加到 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();