博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EFCore执行Sql语句的方法:FromSql与ExecuteSqlCommand
阅读量:5110 次
发布时间:2019-06-13

本文共 5271 字,大约阅读时间需要 17 分钟。

前言

在EFCore中执行Sql语句的方法为:FromSql与ExecuteSqlCommand;在EF6中的为SqlQuery与ExecuteSqlCommand,而FromSql和SqlQuery有很大区别,FromSql返回值为IQueryable,因此为延迟加载的,可以与Linq扩展方法配合使用,但是有不少的坑(EFCore版本为1.1.0),直接执行Sql语句的建议不要使用FromSql,但是EFCore中并没有提供SqlQuery方法,因此下面会贴出SqlQuery的实现代码供大家参考,以便在EFCore中能使用。

 

FromSql和ExecuteSqlCommand的使用

测试时使用了SqlServer2008和SqlServer Profiler进行Sql语句捕捉,EFCore的版本为1.1.0。

测试的Entity Model与DbContext

 
View Code

 

ExecuteSqlCommand

EFCore的ExecuteSqlCommand和EF6的一样,执行非查询的Sql语句:

1             var db = new MSSqlDBContext();2             db.Database.ExecuteSqlCommand($"update {nameof(Person)} set name=@name where id=@id", new[] 3             {4                 new SqlParameter("name", "tom1"),5                 new SqlParameter("id", 1),6             });

 

FromSql

官方参考文档:

简单使用

1             var db = new MSSqlDBContext();2             var name = "tom";3             var list = db.Set
().FromSql($"select * from {nameof(Person)} where {nameof(name)}=@{nameof(name)} ", 4 new SqlParameter(nameof(name), name)).ToList();

生成的Sql:

exec sp_executesql N'select * from Person where name=@name ',N'@name nvarchar(3)',@name=N'tom'

注意:

默认生成的为Person的Model,如果Select获取的字段中不包含Person中的某字段就会抛异常了,例如:下面的语句只获取name字段,并没有包含Person的其他字段,那么抛异常:The required column 'id' was not present in the results of a 'FromSql' operation.

db.Set
().FromSql($"select name from {nameof(Person)} ").ToList();

那么改为:

db.Set
().Select(l => l.name).FromSql($"select name from {nameof(Person)} ").ToList();

 

执行存储过程

1             var db = new MSSqlDBContext();2             db.Set
().FromSql("exec testproc @id", new SqlParameter("id", 1)).ToList();

生成的Sql:

exec sp_executesql N'exec testproc @id',N'@id int',@id=1

 

与Linq扩展方法配合使用

1             var db = new MSSqlDBContext();2             db.Set
().FromSql($"select * from {nameof(Person)} where name=@name ", new SqlParameter("@name", "tom"))3 .Select(l => new { l.name, l.birthday }).ToList();

生成的Sql:

 
View Code

inner join + order by

1             var db = new MSSqlDBContext();2              (from p in db.Set
().FromSql($"select * from {nameof(Person)} ")3 join a in db.Set
().Where(l => true)4 on p.addrid equals a.id5 select new { p.id, p.name, a.fullAddress }).OrderBy(l => l.id).ToList();

生成的Sql:

 
View Code

left join + order by

1             var db = new MSSqlDBContext();2              (from p in db.Set
().FromSql($"select * from {nameof(Person)} ")3 join a in db.Set
().Where(l => true)4 on p.addrid equals a.id into alist5 from a in alist.DefaultIfEmpty()6 select new { p.id, p.name, fullAddress = a == null ? null : a.fullAddress }).OrderBy(l => l.id).ToList();

生成的Sql:(生成的Sql很有问题,order by后面多了[p].[addrid],而且生成的select的字段也是多了)

SELECT [p].[id], [p].[addrid], [p].[birthday], [p].[name], [t].[id], [t].[fullAddress], [t].[lat], [t].[lon]FROM (    select * from Person ) AS [p]LEFT JOIN (    SELECT [l0].[id], [l0].[fullAddress], [l0].[lat], [l0].[lon]    FROM [Address] AS [l0]) AS [t] ON [p].[addrid] = [t].[id]ORDER BY [p].[id], [p].[addrid]

FromSql换成Where扩展方法试试:

1             (from p in db.Set
().Where(l => true)2 join a in db.Set
().Where(l => true)3 on p.addrid equals a.id into alist4 from a in alist.DefaultIfEmpty()5 select new { p.id, p.name, fullAddress = a == null ? null : a.fullAddress }).OrderBy(l => l.id).ToList();

EFCore生成的Sql(order by后面还是多了[addrid],select的字段也是多了):

SELECT [l].[id], [l].[addrid], [l].[birthday], [l].[name], [t].[id], [t].[fullAddress], [t].[lat], [t].[lon]FROM [Person] AS [l]LEFT JOIN (    SELECT [l1].[id], [l1].[fullAddress], [l1].[lat], [l1].[lon]    FROM [Address] AS [l1]) AS [t] ON [l].[addrid] = [t].[id]ORDER BY [l].[id], [l].[addrid]

而在EF6中生成的Sql,比EFCore的生成好多了:

SELECT     [Project1].[id] AS [id],     [Project1].[name] AS [name],     [Project1].[C1] AS [C1]    FROM ( SELECT         [Extent1].[id] AS [id],         [Extent1].[name] AS [name],         CASE WHEN ([Extent2].[id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE [Extent2].[fullAddress] END AS [C1]        FROM  [dbo].[Person] AS [Extent1]        LEFT OUTER JOIN [dbo].[Address] AS [Extent2] ON [Extent1].[addrid] = [Extent2].[id]    )  AS [Project1]    ORDER BY [Project1].[id] ASC

结果说明

FromSql不能代替原来EF6的SqlQuery使用,而且结合Linq扩展方法使用的时候生成的Sql会存在一些问题(EFCore版本为:1.1.0),那么为了能在EFCore中执行Sql查询语句,下面提供对SqlQuery方法的实现。

SqlQuery的实现

 
View Code

使用:

1             var db = new MSSqlDBContext();2             string name = "tom";3             var list = SqlQuery
(db,4 $" select p.id, p.name, a.fullAddress, a.lat, a.lon " +5 $" from ( select * from {nameof(Person)} where {nameof(name)}=@{nameof(name)} ) as p " +6 $" left join {nameof(Address)} as a on p.addrid = a.id ",7 new[] { new SqlParameter(nameof(name), name) });

生成的Sql:

exec sp_executesql N' select p.id, p.name, a.fullAddress, a.lat, a.lon  from ( select * from Person where name=@name ) as p  left join Address as a on p.addrid = a.id ',N'@name nvarchar(3)',@name=N'tom'

转载于:https://www.cnblogs.com/chenliyang/p/6553051.html

你可能感兴趣的文章
Export class type
查看>>
通过反射来修改对象里面的值
查看>>
Gym - 100221D 一题一直没过的dfs,,应该是纯手动码?
查看>>
Codeforces Round #172 (Div. 2) D. Maximum Xor Secondary 单调栈应用
查看>>
...
查看>>
关于大根堆 (模板)
查看>>
堆排序
查看>>
java 垃圾回收总结(可达性分析 引用分类
查看>>
洛谷 P2024 [NOI2001]食物链 (并查集)
查看>>
CSS Sticky Footer实现
查看>>
python之路_socketserver模块
查看>>
一款我用了好多年的多线程FTP软件
查看>>
GreenDao数据库的简单使用
查看>>
Starting cloudera-scm-server: * Couldn't start cloudera-scm-server的解决办法(图文详解)
查看>>
Hadoop的ChainMapper和ChainReducer使用案例(链式处理)(四)
查看>>
linux 强制删除yum安装的php7.2
查看>>
uiautomator_python使用汇总
查看>>
tomcat cluster session同步时保存map数据遇到的问题
查看>>
Javascript备忘录-枚举一个对象的所有属
查看>>
Asp.net MVC DefaultModelBinder分析
查看>>