C#使用左右连接创建3个表的lambda表达式
Posted
技术标签:
【中文标题】C#使用左右连接创建3个表的lambda表达式【英文标题】:C# Create lambda expression with Left and right Join with 3 tables 【发布时间】:2021-09-16 09:28:37 【问题描述】:我目前正在为我的应用程序开发一个搜索过滤器,但我在按特定键进行过滤时遇到问题,当我制作 lambda 表达式时,它会为我提供范围内的所有值,但我不知道我还需要什么添加以正确获取过滤器。
我有三个带有各自外键的表: 表 A:id_contract, 表 B:id_build 和 id_contract, 表 C:id_build
实体如下: 表A
public partial class TableA
public TableA()
this.TableB = new List<TableB>();
public int id_contract get; set; //Primary Key
public int id_client get; set; //FK another table not important for now
public int contract_name get; set; //Information
表 B
public partial class TableB
public int id_tableB get; set; //primary key (not use)
public int id_contract get; set; //FK Table A
public int id_build get; set; //FK Table C
public virtual TableC TableC get; set;
public virtual TableA TableA get; set;
表 C
public partial class TableC
public TableC()
this.TableB = new List<TableB>();
public int id_build get; set; //Primary Key
public string build_code get; set;
public virtual List<TableB> TableB get; set;
过滤器的参数来自控制器内部的 id_builds 列表,然后我使用 Contains 检查表是否具有相应的值。
我的SQL查询如下:
SELECT c.contract_name, b.build_value, MAX(p.update_date) AS [updt_date]
FROM
(
SELECT id_contract, MAX(id_build) AS id_build
FROM [Table B]
GROUP BY id_contract
) d
JOIN [Table B] P ON p.id_contract = d.id_contract AND p.id_build = d.id_build
RIGHT JOIN [Table A] c WITH(NOLOCK) ON p.id_contract = c.id_contract
LEFT JOIN [Table C] b WITH(NOLOCK) ON p.id_build = b.id_build
/*This where is where i filter it, and the correct value must be based from id_build as below, i commented it to test and get all values from query before.*/
WHERE c.contract_name <> 0 AND c.id_company = 1 AND c.ativo = 1 --and b.id_build = XXX
GROUP BY c.contract_name, b.build_value
当我在不按 XXX 值过滤的情况下运行此查询时,我会得到所有 750 个结果,这适用于任何值,并且使用过滤器,我会通过 id_build 获得 61 个结果,这些结果对应于我从过滤器中给出的任何值。
我目前在 C# 中的 lambda 表达式如下:
results = db.TableA
.Join(db.TableB, tbA => id_contract, tbB => id_contract, (tbA , tbB ) => new tbA, Key = tbB.id_build)
.Join(db.TableC, tbC => tbC.Key, FKTableB=> TableB.id_build, (tbC , FKTableB) => new tbC, FKTableB)
.Where(c => c.tbC.tbA.ativo == true && c.tbC.tbA.id_company == 1 && id_build.Contains(c.FKTableB.id_build))
/*ignore this select inside content, but consider it as i need this output to be printed out.*/
.Select(x => new
x.tbC.tbA.id_contract,
contract_name = x.tbC.tbA.contrato + " - " +
x.tbC.tbA.client_name
).ToList();
我不知道如何在这种状态下复制 Join。
谢谢!
【问题讨论】:
你能展示实体类吗? (表A、表B、表C) 您好@vernou,已添加实体。 为什么在可以使用导航属性(A.TableB
等)的同时加入 LINQ 查询?使查询更容易。 LINQ 查询可以是db.TableA.Where(...)
,无需任何连接。
【参考方案1】:
我不知道你到底想要什么,但我用 lambda 表达式实现了你确切的 sql 查询。
请使用以下类进行查询。我将update_date
添加到TableB
类和build_value
到TableC
类。和id_company
和ativo
到TableA
类。
public partial class TableA
public TableA()
this.TableB = new List<TableB>();
public int id_contract get; set; //Primary Key
public int id_client get; set; //FK another table not important for now
public int contract_name get; set; //Information
public int id_company get; set; //Information
public int ativo get; set;
public virtual List<TableB> TableB get; set;
public partial class TableB
public int id_tableB get; set; //primary key (not use)
public int id_contract get; set; //FK Table A
public int id_build get; set; //FK Table C
public DateTime update_date get; set;
public virtual TableC TableC get; set;
public virtual TableA TableA get; set;
public partial class TableC
public TableC()
this.TableB = new List<TableB>();
public int id_build get; set; //Primary Key
public string build_code get; set;
public int build_value get; set;
public virtual List<TableB> TableB get; set;
lambda 表达式
var results = db.TableB
.GroupBy(a => a.id_contract)
.Select(a => new
id_contract = a.Key,
id_build = a.Max(x => x.id_build)
)
.Join(db.TableB,
a => new a.id_contract, a.id_build ,
b => new b.id_contract, b.id_build ,
(a, b) => new id_contract = a.id_contract, id_build = a.id_build, tB = b
)
.Join(db.TableA,
a => a.id_contract,
b => b.id_contract,
(a, b) => new id_contract = a.id_contract, id_build = a.id_build, tB = a.tB, tA = b
)
.Join(db.TableC,
a => a.id_build,
b => b.id_build,
(a, b) => new id_contract = a.id_contract, id_build = a.id_build, tB = a.tB, tA = a.tA, tC = b )
.Where(a=>a.tA.contract_name != 0 && a.tA.id_company == 1 && a.tA.ativo == 1)
.GroupBy(a => new a.tA.contract_name, a.tC.build_value )
.Select(a => new
contract_name = a.Key.contract_name,
build_value = a.Key.build_value,
updt_date = a.Max(x => x.tB.update_date)
).ToList();
【讨论】:
非常感谢,它帮助我了解了我遗漏的地方,我的目标是调整该查询以充当基于表 C 中的 id_build 的过滤器,现在它可以工作了!以上是关于C#使用左右连接创建3个表的lambda表达式的主要内容,如果未能解决你的问题,请参考以下文章