码迷,mamicode.com
首页 > 其他好文 > 详细

RichErp EfCore linq的正确写法

时间:2018-08-27 21:43:06      阅读:160      评论:0      收藏:0      [点我收藏+]

标签: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条件是没有限制的,用什么函数都行。

 

RichErp EfCore linq的正确写法

标签:nta   lin   dex   apply   表数   isa   ==   操作   写法   

原文地址:https://www.cnblogs.com/richerp/p/9543849.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!