标签:nta lin dex apply 表数 isa == 操作 写法
RichErp EfCore linq的正确写法
好多网友不知道ef 的linq 如何写才能高效且简洁,我总结了一下,归纳如下:
如: 从操作员表usergl_czy中获取数据
1、得到一行数据
var czy1 = (from a in dbContext.usergl_czy
where a.czybm == "9999"
select a).FirstOrDefault();
对应的sql为:
SELECT TOP(1) [a].[czyid], [a].[bm], [a].[czy], [a].[czybm], [a].[dh], [a].[isallkehu], [a].[isrun], [a].[note]
FROM [usergl_czy] AS [a]
WHERE [a].[czybm] = N‘9999‘
注意:有 Top 1
2、得到一组数据
var czy1 = (from a in dbContext.usergl_czy
where a.czybm.Contains("9999")
select a).ToList();
对应的sql为:
SELECT [a].[czyid], [a].[bm], [a].[czy], [a].[czybm], [a].[dh], [a].[isallkehu], [a].[isrun], [a].[note]
FROM [usergl_czy] AS [a]
WHERE CHARINDEX(N‘9999‘, [a].[czybm]) > 0
注意:没有 Top 1
2、外键关联其他表,如获取部门数据class_class
形式一:
var czy1 = (from a in dbContext.usergl_czy
join bb in dbContext.class_class
on a.bm equals bb.child into bbs
from b in bbs.DefaultIfEmpty()
where a.czybm == "9999"
select new
{
user = a,
part = b
}).ToList();
对应的sql为:
SELECT [a].[czyid], [a].[******], [bb].[child], [bb].[bm], [bb].[childname]
FROM [usergl_czy] AS [a]
LEFT JOIN [class_class] AS [bb] ON [a].[bm] = [bb].[child]
WHERE [a].[czybm] = N‘9999‘
注意:left join
形式二:
var czy1 = (from a in dbContext.usergl_czy
from b in dbContext.class_class.Where(x => x.child == a.bm).DefaultIfEmpty()
where a.czybm == "9999"
select new
{
user = a,
part = b
}).ToList();
对应的sql为:
SELECT [a].[czyid], [a].[bm],a.****** [略],[t0].[child], [t0].[childname]
FROM [usergl_czy] AS [a]
CROSS APPLY (
SELECT [t].[child], [t].[childname]
FROM (
SELECT NULL AS [empty]
) AS [empty]
LEFT JOIN (
SELECT [x].[child], [x].[childname]
FROM [class_class] AS [x]
WHERE [x].[child] = [a].[bm]
) AS [t] ON 1 = 1
) AS [t0]
WHERE [a].[czybm] = N‘9999‘
对应的sql有点复杂,感觉不如形式一简洁。
部门表class_class中的数据可以缺失,但不影响获取的主表数据
注意:DefaultIfEmpty(),CROSS APPLY,LEFT JOIN
3、内键关联其他表,如获取部门数据class_class
形式一:
var czy1 = (from a in dbContext.usergl_czy
join bb in dbContext.class_class
on a.bm equals bb.child into bbs
from b in bbs
where a.czybm == "9999"
select new
{
user = a,
part = b
}).ToList();
对应的sql为:
SELECT [a].[czyid], [a].******, [bbb].[child], [bbb].[bm], [bbb].[childname]
FROM [usergl_czy] AS [a]
INNER JOIN [class_class] AS [bbb] ON [a].[bm] = [bbb].[child]
WHERE [a].[czybm] = N‘9999‘
注意: inner join
形式二:
var czy1 = (from a in dbContext.usergl_czy
from b in dbContext.class_class.Where(x => x.child == a.bm)
where a.czybm == "9999"
select new
{
user = a,
part = b
}).ToList();
对应的sql为:
SELECT [a].[czyid], [a].[******], [x].[child], [x].[bm], [x].[childname]
FROM [usergl_czy] AS [a]
CROSS JOIN [class_class] AS [x]
WHERE ([x].[child] = [a].[bm]) AND ([a].[czybm] = N‘9999‘)
注意:没有了DefaultIfEmpty(),CROSS JOIN代替了
4、in 的用法
string[] ids = new string[] { "0001","0002","0003"};
var czy1 = (from a in dbContext.usergl_czy
join bb in dbContext.class_class
on new { id = a.bm,id2=a.czyid } equals new { id = bb.child,id2=bb.childname } into bbs
from b in bbs
where ids.Contains(a.czybm)
select new
{
user = a,
part = b
}).ToList();
对应的sql为:
SELECT [a].[czyid], [a].[******], [bb].[child], [bb].[bm], [bb].[childname]
FROM [usergl_czy] AS [a]
INNER JOIN [class_class] AS [bb] ON ([a].[bm] = [bb].[child]) AND ([a].[czyid] = [bb].[childname])
WHERE [a].[czybm] IN (N‘0001‘, N‘0002‘, N‘0003‘)
注意:ids可以为List<string>。
5、获取其他额外数据:
string[] ids = new string[] { "0001","0002","0003"};
var czy1 = (from a in dbContext.usergl_czy
join bb in dbContext.class_class
on new { id = a.bm } equals new { id = bb.child } into bbs
from b in bbs
where ids.Contains(a.czybm)
select new
{
user = a,
part = b,
roles = (from c in dbContext.usergl_czyrole
where c.czyid == a.czyid
select c) (.ToList())
}).ToList();
对应的sql为:
SELECT [a].[czyid], [a].[****], [bb].[child], [bb].[bm], [bb].[childname]
FROM [usergl_czy] AS [a]
INNER JOIN [class_class] AS [bb] ON [a].[bm] = [bb].[child]
WHERE [a].[czybm] IN (N‘0001‘, N‘0002‘, N‘0003‘)
注意:生成的sql里面没有usergl_czyrole,原来是sql server另外自动生成了sql语句,这样,数据量大时,是不是很慢?
exec sp_executesql N‘SELECT [c].[czyid], [c].[roleid]
FROM [usergl_czyrole] AS [c]
WHERE [c].[czyid] = @_outer_czyid‘,N‘@_outer_czyid nvarchar(450)‘,@_outer_czyid=N‘0001‘
6、还可以这样设计,在类外面再套一层,这样灵活度大大提高:
var czy1 = (from a in dbContext.usergl_czy
join bb in dbContext.class_class
on new { id = a.bm } equals new { id = bb.child } into bbs
from b in bbs
where ids.Contains(a.czybm)
select new Usergl_czyExt
{
usergl_czy = a,
PartExt = new Class_classExt
{
class_class = b
}
}).ToList();
生成的sql命令没有什么不同。
注意:在efcore中这样是允许的,但在.net framework中是不允许的。
public class Usergl_czyExt : RichErpEntityObject
{
public usergl_czy usergl_czy{get;set;}
public Class_classExt PartExt{get;set;}
}
最后,总结一个规律:
(1)、最好把您要获取数据表放到第一行,其他表都用DefaultIfEmpty()关联,这样可能获取的数据中主表是全的,不会遗漏。
(2)、形式一的linq较复杂,但生成的sql高效,形式二的linq简洁,但生成的sql莫名其妙,但结果都一样。
还是推荐用形式一吧
(3)、如果有涉及多列的where条件,可以这样写:
var czy1 = (from a in dbContext.usergl_czy
join bb in dbContext.class_class
on new { id = a.bm,id2 = a.bm2 } equals new { id = bb.child,id2 = bb.child2 } into bbs
from b in bbs
where a.czybm == "9999"
select new
{
user = a,
part = b
}).ToList();
(4)、直接对数据库操作的linq,里面的where条件是有限的,对于List<T>的linq,where条件是没有限制的,用什么函数都行。
标签:nta lin dex apply 表数 isa == 操作 写法
原文地址:https://www.cnblogs.com/richerp/p/9543849.html