sql - 将 sql 连接脚本转换为 lambda 或 linq
问题描述
如何将此脚本转换为 lambda 或 linq ?
select a.PayoutID,b.PayoutName
from [dbo].[PayoutsOfUser] a
inner join [dbo].[Payout] b on a.PayoutID = b.PayoutID
inner join [dbo].[Users] c on a.UserID = c.UserID
where c.UserID = 16
解决方案
方法语法(= 带有 lambda 表达式的语法)比查询语法具有更多功能。因此,我更喜欢在查询语法之上使用方法语法。
但是有一个例外:当连接三个或更多表时,方法语法看起来很可怕,就像 Sebu 在他的回答中显示的那样。也显示在这个答案中,其中比较了连接三个表的两种方法
IQueryable
无论是使用方法语法还是查询语法,内部的表达式都是一样的,因此生成的 SQL 语句不会有太大差异。
因此我的建议是:尽可能使用方法语法,但为了可读性、更少的错误、更好的可维护性:使用查询语法连接三个表。
如果您必须经常连接三个表,请考虑创建一个隐藏连接完成方式的扩展函数:
请参阅:扩展功能揭秘
以下函数采用三个输入序列:IQueryable、IQueryable 和 IQueryable。
它在使用 T1Join1Selector 和 T2Join1Selector 提取的键上连接前两个序列,
如果在使用 T2Join2Selector 和 T3Join2Selector 提取的键上连接后两个序列
从每个匹配的 T1 / T2 / T3 它根据 resultSelector 创建一个结果
public static IQueryable<TResult> Join<T1, T2, T3,
TKeyJoin1, TKeyJoin2, TResult>(
this IQueryable<T1> table1,
IQueryable<T2> table2,
IQueryable<T3> table3,
Expression<Func<T1, TKeyJoin1>> table1Join1KeySelector,
Expression<Func<T2, TKeyJoin1>> table2Join1KeySelector,
Expression<Func<T2, TKeyJoin2>> table2Join2KeySelector,
Expression<Func<T3, TKeyJoin2>> table3Join2KeySelector,
Expression<Func<T1, T2, T3, Tresult>> resultSelector)
{
return Tabl1.Join(table2, // join table1 and table2
t1 => table1Join1KeySelector(t1), // select the key from table1 for the first join
t2 => table2Join1KeySelector(t2), // select the key from table2 for the first join
(t1, t2) => new // remember the matching records as T1 and T2
{
T1 = t1,
T2 = t2,
})
// use this as input for the second join:
.Join(table3,
// use the T2 in the result of the first join as key for the second join
joinedT1andT2 => table2Join2KeySelector(joinedT1andT2.T2),
t3 => table3Join2KeySelector(t3), // select the key from table3 for the 2nd join
// and use the result of the first and second join to create a linq-result:
(joinedT1andT2, t3) => resultSelector(joinedT1andT2.T1, joinedT1andT2.T2, T3);
}
或者使用查询语法连接三个表:
public static IQueryable<TResult> Join<T1, T2, T3,
TKeyJoin1, TKeyJoin2, TResult>(
this IQueryable<T1> table1,
IQueryable<T2> table2,
IQueryable<T3> table3,
Expression<Func<T1, TKeyJoin1>> table1Join1KeySelector,
Expression<Func<T2, TKeyJoin1>> table2Join1KeySelector,
Expression<Func<T2, TKeyJoin2>> table2Join2KeySelector,
Expression<Func<T3, TKeyJoin2>> table3Join2KeySelector,
Expression<Func<T1, T2, T3, Tresult>> resultSelector)
{
return select resultSelector(table1, table2, table3)
from table1
join table2 on table1Join1KeySelector(table1) == table2Join1KeySelector(table2)
join table3 on table2Join2KeySelector(table2) == table3Join2KeySelector(table3)
}
用法类似于使用方法语法连接两个表的方式:
var result = a.Join(b, c, // join your tables a, b, c
t1 => t1.PayoutId, // first join on a.PayoutID = b.PayoutID
t2 => t2.PayoutId,
t2 => t2.UserId, // second join on b.UserID = c.UserID
t3 => t3.UserId,
(t1, t2, t3) => new // from the matching records create one new object
{
PayoutId = t1.PayoutId,
PayoutName = t2.PayoutName,
...
});
我看到您的第二次加入是在 a 和 c 上,而我的第二次加入是在 b 和 c 上。我相信您会知道如何根据需要重写代码
由于此函数的结果是一个 IQueryable,因此该函数只会更改 Expression。查询尚未执行。因此,您可以安全地将其与其他 IQueryable 函数混合使用:
var resultQuery = a.Where(t1 => t1.Name = ...)
.Join( /* 3-table join as described above */ )
.GroupBy(joinResult => ...)
.Take(4);
查询仍未执行,直到您执行不返回 的操作IQueryable
,例如ToList
// FirstOrDefault
/ Any
...
推荐阅读
- sensors - ESP32 读取 ULP 协处理器中的 DHT22 传感器
- xamarin - Xamarin 表单搜索栏填充
- json - 带有来自 httpClient 的参数的 Azure Runbook Webhook
- javascript - 如果值为真,则查找子属性键值并返回父对象 LODASH
- excel - Excel - 逻辑公式拼图
- html - 无法让 Bootstrap4 列表内联以相互放置元素
- c++ - C++ 使用数组插入二叉搜索树
- cross-platform - 我应该使用哪种跨平台编码语言?
- excel - 在一个工作表中查找单元格并将值返回到另一个工作表中
- excel - 鼠标悬停结束后如何结束宏(或触发不同的宏)