EF Core - 2.0 和 2.1 发现
EF Core 目前已经升级到了2.1版本。 但是我之前有个项目是2.0 版本的,今天把sql语句弄出来看以下发现了不少问题。目前是建议如果使用了2.0版本的用户可以升级到2.1 。毕竟2.1还是修复了许多问题的。废话不多说,总结以下下面问题:
一、 2.0版本 Join 之后
用过Linq To Sql 都知道。如果连接两个表,我这边的例子是:
var query = from p in db.PurchaseProject join e in db.Employee on p.ProjectManagerId equals e.Id into pe from pei in pe.DefaultIfEmpty() select new PurchaseProjectListSearchModel() { Id = p.Id, TenderingNo = p.TenderingNo, ProjectName = p.ProjectName, PurchaseKind = p.PurchaseKind, ProjectManagerId = p.ProjectManagerId, ProjectManagerName = pei.RealName, BidOpenDate = p.BidOpenDate, Remark = p.Remark, AgentName = p.AgentName, CreatedOn = p.CreatedOn, Number = p.Number, };
var listData = query.AsNoTracking().OrderBy(m => m.Id).Skip(0).Take(10).ToList();
我们用Miniprofiler 来查看以下生产的sql语句如下:
没错,我们是使用了left join,但是程序并没有帮我们翻译成分页语句。这个问题在2.1 版本偷偷的得到改善,而微软官方文档却没有做出修改的解释。
二、 2.1 版本Group By 受到干扰
看下下面的代码:
var d7 = (from n in db.TestBF.Where(m => m.Num1 > 1) group n by n.Number into g select new TestModel() { CreateTime = g.Min(m => m.CreateOn), Total = g.Min(m => m.Num1) + g.Min(m => m.Num2), }).ToList();
真正的执行的语句是:
这个我们很容易理解,就是正常的一个Group by ;下面我们把查询的代码修改一下:
var d7 = (from n in db.db.Where(m => m.Num1 > 1) group n by n.Number into g select new TestModel() { CreateTime = g.Min(m => m.CreateOn), Total = g.Min(m => m.Num1) + g.Min(m => m.Num2), Num = g.Sum(m => m.Num1 ?? 0) }).ToList();
数据库中的Num1是Int? 类型,在使用双目运算符??以后我们看一下真正执行的sql语句:
让我们惊讶的是没有了Group by 而是把所有数据查询出来在内存里面执行了。还有简单的一些时间转换ToString()
var d7 = (from n in db.TestBF.Where(m => m.Num1 > 1) group n by n.Number into g select new TestModel() { CreateTime = g.Min(m => m.CreateOn), Total = g.Min(m => m.Num1) + g.Min(m => m.Num2), //Num = g.Sum(m => m.Num1 ?? 0) TimeStr = g.Min(m => m.CreateOn.ToString()) }).ToList();
最终都会把group by 干扰掉。当然解决方法是把数据库字段原封不动的映射到外部的Model,然后再把查询出来的数据进行转换,不要轻易在select里面进行函数使用,当然了有些语法还是支持的,比如:
var d82 = (from n in db.TestBF select new TestModel() { CreateTime = n.CreateOn, Total = n.Num1 + n.Num2, Num = n.Num1.GetValueOrDefault(0), TimeStr = n.CreateOn.ToString() }).Skip(1).Take(2).ToList();
如果是分页的话:
接下来看下Join语句之后进行一个group by ,这也是我们平时做查询经常用到的
using (var db = new MyDbContext()) { var query = from s in db.Student join c in db.SC on s.sid equals c.sid into sc from sci in sc.DefaultIfEmpty() group new { s,sci} by new { s.sid, s.sname } into g select new { sid = g.Key.sid, sname = g.Key.sname, //scount = g.Count(), //total = g.Sum(m=>m.sci!=null ? m.sci.score : 0) }; var data = query.ToList(); }
最终,EF又让我们失望了,这个查询就是查询所有同学的学号、姓名、选课数、总成绩。Student是学生表,SC是学生课程成绩表。所有,EF Core还有一段路要走...
执行语句并不一定是我们语法想得到的。所以....
好了,今天分享就到这。