EntityFramework Core Raw SQL
前言
本节我们来讲讲EF Core中的原始查询,目前在项目中对于简单的查询直接通过EF就可以解决,但是涉及到多表查询时为了一步到位就采用了原始查询的方式进行。下面我们一起来看看。
EntityFramework Core Raw SQL
基础查询(执行SQL和存储过程)
啥也不说了,拿起键盘就是干,如下:
public class HomeController : Controller { private IBlogRepository _blogRepository; public HomeController(IBlogRepository blogRepository) { _blogRepository = blogRepository; } public IActionResult Index() { var list = _blogRepository.GetList(); return Ok(); } }
public class BlogRepository : EntityBaseRepository<Blog>, IBlogRepository { private EFCoreContext _efCoreContext; public BlogRepository(EFCoreContext efCoreContext) : base(efCoreContext) { _efCoreContext = efCoreContext; } public IEnumerable<Blog> GetList() { var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("select * from Blog"); return iQueryTable.ToList(); } }
下面我们来看看存储过程。
CREATE PROCEDURE dbo.GetBlogList AS BEGIN SELECT * FROM dbo.Blog END GO
public IEnumerable<Blog> GetList() { var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("EXECUTE dbo.GetBlogList"); return iQueryTable.ToList(); }
参数查询
利用参数化存储过程查询。
ALTER PROCEDURE [dbo].[GetBlogList] @id INT
AS BEGIN SELECT * FROM dbo.Blog WHERE Id = @id END
结果利用FromSql就变成了如下:
public IEnumerable<Blog> GetList() { var Id = new SqlParameter("Id", "1"); var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("EXEC dbo.GetBlogList {0}", 1); return iQueryTable.ToList(); }
上述是利用string.format的形式来传参,我们也可以利用SqlParameter来传参,如下:
public IEnumerable<Blog> GetList() { var Id = new SqlParameter("Id", "1"); var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("EXEC dbo.GetBlogList @id", Id); return iQueryTable.ToList(); }
我们通过开启调试,可以清晰看到执行的存储过程。
通过如上我们知道参数化查询有两种形式,下面我们再来看看linq查询。
linq查询
上述我们演示一直直接使用FromSql,其实在此之后我们可以继续通过linq来进行查询,如下:
public IEnumerable<Blog> GetList() { var Id = new SqlParameter("Id", "2"); var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("EXEC dbo.GetBlogList @id", Id).Where(d => d.Name == "efcore2"); return iQueryTable.ToList(); }
之前我们映射了Blog和Post之间的关系,这里我们只能查询出Blog表的数据,通过对上述linq的讲解,我们完全可以通过inlcude来显式加载Post表数据,如下:
public IEnumerable<Blog> GetList() { var Id = new SqlParameter("Id", "2"); var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("EXEC dbo.GetBlogList @id", Id).Include(d => d.Posts); return iQueryTable.ToList(); }
好吧,明确告诉我们对于存储过程是不支持Inlude操作的,所以要想Include我们只能进行简单的查询,如下:
public IEnumerable<Blog> GetList() { var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("select * from blog").Include(d => d.Posts); return iQueryTable.ToList(); }
查找官网资料时发现居然对表值函数(TVF)是可以Include的,创建内嵌表值函数如下:
USE [EFCoreDb] GO IF OBJECT_ID('dbo.GetBlog') IS NOT NULL DROP FUNCTION dbo.GetBlog; GO CREATE FUNCTION dbo.GetBlog (@Name VARCHAR(max)) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT Id, Name, Url FROM dbo.Blog WHERE Name = @Name GO
调用如下:
public IEnumerable<Blog> GetList() { var name = "efcore2"; var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("select * from [dbo].[GetBlog] {0}", name).Include(d => d.Posts); return iQueryTable.ToList(); }
结果出乎意料的出现语法错误:
通过SQL Server Profiler查看发送的SQL语句如下:
这能不错么,官网给的示例也是和上述一样,如下:
只是按照和他一样的搬过来了,未曾想太多,还是粗心大意了,想了好一会,按照我们正常调用表值函数即可,我们需要用括号括起来才行,如下:
public IEnumerable<Blog> GetList() { var name = "efcore2"; var iQueryTable = _efCoreContext.Set<Blog>(). FromSql("select * from [dbo].[GetBlog] ({0})", name).Include(d => d.Posts); return iQueryTable.ToList(); }
上述将[dbo.GetBlog]和({0})隔开和挨着都可以。这个时候才不会出现语法错误。执行的SQL如下才是正确的。
好了,到了这里关于EF Core中原始查询我们就告一段落了,其中还有一个知识点未谈及到,在EF Core我们可以直接通过底层的ADO.NET来进行查询,我们来看下:
底层ADO.NET查询
public IEnumerable<Blog> GetList() { var list = new List<Blog>(); using (var connection = _efCoreContext.Database.GetDbConnection()) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandText = "SELECT * FROM dbo.Blog"; using (SqlDataReader reader = command.ExecuteReader() as SqlDataReader) { while (reader.Read()) { var blog = new Blog(); blog.Id = Convert.ToInt32(reader["Id"]); blog.Name = reader["Name"].ToString(); blog.Url = reader["Url"].ToString(); list.Add(blog); } } } } return list; }
总结
我们本节讲述了EF Core中的原始查询,相比较之前EF版本的原始查询使用更加灵活了一点,但是缺陷还是展露无遗,依然只能查出所有的列且必须匹配,同时呢,若我们想执行事务,目前还不支持底层的TranscationScope仅仅支持BeginTranscation。
相关文章
- ASP .NET CORE MVC 部署Windows 系统上 IIS具体步骤---.Net Core 部署到 IIS位系统中的步骤
- SQL SERVER 2012启动失败 because upgrade step 'SSIS_hotfix_install.sql' 失败
- 【学习总结】SQL的学习-2-sql操作
- 重新整理 .net core 实践篇————配置系统——军令(命令行)[六]
- 重新整理.net core 计1400篇[三] (.net core 如何源代码调试和查看源码 )
- .net core 认证与授权(三)
- 【学习总结】SQL的学习-2-sql操作
- 重新整理 .net core 实践篇—————配置系统之强类型配置[十]
- [SQL] sql server中如何查看执行效率不高的语句
- SQL SERVER服务器链接连接(即sql server的跨库连接)
- 《ASP.NET Core 3框架揭秘》勘误[逐步完善中…]
- [ASP.NET Core 3框架揭秘] 依赖注入[9]:实现概述
- UI Startup analysis - sap.ui.core.Core what js files are loaded
- SAP UI5 GM6 require sap.ui.core.Core
- SAP 电商云 Spartacus UI 回归测试 b2b-replenishment-checkout-flow.core-e2e-spec.ts
- Atitit sql查询语法 SQL SELECT完整语法3 1.SELECT语法3 2.FROM子句5 3.WHERE子句6 下面两张表将在后面使用到7 1.比较运算符7 2.逻辑
- Atitit if else 选择决策流程ast对比 sql java 表达式类型 binaryExpression hase left and rit expr 目录 1.1. Sql1
- ML之xgboost:解读用法之xgboost库的core.py文件中的get_score(importance_type=self.importance_type)方法
- 成功解决pandas.core.frame.DataFrame格式数据与numpy.ndarray格式数据不一致导致无法运算问题
- 已解决 I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with on
- SQL VQ11 找出sql类题目的单次最大刷题数
- 阅读zepto.js的core中的Core methods
- 010-Hadoop Hive sql语法详解5-HiveQL与SQL区别
- SQL注入 Sqli-labs-Less-21(笔记)——还是回显注入 使用union select即可 但是要注意sql括号闭合 也可以报错注入
- ASP.NET Core使用EF Core操作MySql数据库
- net core HTTP Error 500.31 - Failed to load ASP.NET Core runtime HTTP Error 500.30