将 SQL 转换为 LINQ 查询理解:
- 将子选择转换为单独声明的变量除非它们引用子选择之外的列,在这种情况下使用括号创建子查询。
- 按 LINQ 子句顺序翻译每个子句,翻译单个单子和聚合运算符 (
DISTINCT
, TOP
, MIN
, MAX
等)转换为应用于整个 LINQ 查询的函数。
- 使用表别名作为范围变量。使用列别名作为匿名类型字段名称。
- 使用匿名类型(
new {
... }
)对于多列(例如在groupby
).
- Use
First().field
从中获取非键值groupby
聚合范围变量。
- 使用 EF 或 EF Core 时,翻译
JOIN
导航属性中的子句可能使用.Include()
.
- 否则
JOIN
多个子句AND
两个表之间的 ed 相等测试应转换为两侧的匿名对象equals
.
-
JOIN
并非全部相等测试的条件AND
必须使用处理where
连接外部的子句,或带有叉积 (from
... from
...) 进而where
。如果你正在做LEFT JOIN
, 添加一个 lambdaWhere
连接范围变量和DefaultIfEmpty()
call.
-
LEFT JOIN
是通过使用模拟into
连接变量并做另一个from
the 连接变量其次是.DefaultIfEmpty()
.
- 翻译多个表
FROM
子句分成多个from
条款。
- 翻译
FROM T1 CROSS APPLY T2
一分为二from
条款,一项用于T1
和一个用于T2
.
- 翻译
FROM T1 OUTER APPLY T2
一分为二from
条款,一项用于T1
和一个用于T2
,但添加.DefaultIfEmpty()
to T2
.
- Replace
COALESCE
与条件运算符 (?:
)and a null
test.
- 翻译
IN
to .Contains()
and NOT IN
to !
...Contains()
,使用文字数组或数组变量作为常量列表。
- 翻译x
BETWEEN
low AND
high to low <=
x &&
x <=
high.
- 翻译
CASE
, ISNULL
and IIF
到三元条件运算符?:
.
-
SELECT *
必须替换为 select range_variable 或连接(包含所有范围变量的匿名对象)。
-
SELECT
列必须替换为select new {
... }
创建具有所有所需字段或表达式的匿名对象。
- 参考计算
SELECT
可以通过重复表达式或使用来翻译列let
在第一次使用之前命名表达式。
- Proper
FULL OUTER JOIN
必须用一个处理扩展方法 https://stackoverflow.com/a/43669055/2557128.
- 翻译
UNION
to Concat
除非两个子查询都是DISTINCT
,在这种情况下你可以翻译为Union
并留下DISTINCT
.
- 翻译具有多个没有结果列的聚合查询
GROUP BY
使用单例GroupBy
: add .GroupBy(r => 1)
(or group
...by 1 into g
),然后翻译聚合函数Select new { }
.
- 日期 数学 和其他一些典范 https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/ef/language-reference/canonical-functions可以使用以下方式访问函数
EF.Functions
获取一个实例DbFunctions
类(EF 核心),EntityFunctions
等级 (EF DbFunctions访问静态方法 (EntityFramework 6.x)。
- 翻译 SQL
LIKE
使用 (EF Core >= 2) 的表达式EF.Functions.Like(column, pattern)
或 (EF 6.x)DbFunctions.Like(column, pattern)
.
将这些规则应用到 SQL 查询中,您将得到:
var subrq = from r in Table_R
group r by r.Id into rg
select new { Id = rg.Key, cnt = rg.Count() };
var ansq = (from c in Table_C
join v in Table_V on c.Id equals v.Id
join r in subrq on c.Id equals r.Id into rj
from r in rj.DefaultIfEmpty()
where c.IdUser == "1234"
group new { c, v, r } by new { c.Id, c.Title, r.cnt } into cvrg
select new {
cvrg.Key.Title,
Nb_V2 = cvrg.Count(),
Nb_V1 = cvrg.Select(cvr => cvr.v.IdUser).Distinct().Count(),
Nb_R = (int?)cvrg.Key.cnt
}).Distinct();
lambda 翻译很棘手,但是转换LEFT JOIN
to GroupJoin
...SelectMany
是所需要的:
var subr2 = Table_R.GroupBy(r => r.Id).Select(rg => new { Id = rg.Key, cnt = rg.Count() });
var ans2 = Table_C.Where(c => c.IdUser == "1234")
.Join(Table_V, c => c.Id, v => v.Id, (c, v) => new { c, v })
.GroupJoin(subr, cv => cv.c.Id, r => r.Id, (cv, rj) => new { cv.c, cv.v, rj })
.SelectMany(cvrj => cvrj.rj.DefaultIfEmpty(), (cvrj, r) => new { cvrj.c, cvrj.v, r })
.GroupBy(cvr => new { cvr.c.Id, cvr.c.Title, cvr.r.cnt })
.Select(cvrg => new { cvrg.Key.Title, Nb_V2 = cvrg.Count(), Nb_V1 = cvrg.Select(cvr => cvr.v.IdUser).Distinct().Count(), Nb_R = (int?)cvrg.Key.cnt });