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。




本文转自Jeffcky博客园博客,原文链接:http://www.cnblogs.com/CreateMyself/p/6254241.html,如需转载请自行联系原作者

目录
相关文章
|
11月前
|
开发框架 前端开发 JavaScript
ASP.NET Core+Element+SQL Server开发校园图书管理系统(二)
ASP.NET Core+Element+SQL Server开发校园图书管理系统(二)
57 0
|
11月前
|
开发框架 JavaScript .NET
ASP.NET Core+Element+SQL Server开发校园图书管理系统(三)(下)
ASP.NET Core+Element+SQL Server开发校园图书管理系统(三)(下)
60 0
ASP.NET Core+Element+SQL Server开发校园图书管理系统(三)(下)
|
11月前
|
SQL 开发框架 前端开发
ASP.NET Core+Element+SQL Server开发校园图书管理系统(完)
ASP.NET Core+Element+SQL Server开发校园图书管理系统(完)
103 0
|
11月前
|
开发框架 JavaScript .NET
ASP.NET Core+Element+SQL Server开发校园图书管理系统(四)(下)
ASP.NET Core+Element+SQL Server开发校园图书管理系统(四)(下)
78 0
|
11月前
|
开发框架 前端开发 JavaScript
ASP.NET Core+Element+SQL Server开发校园图书管理系统(四)(上)
ASP.NET Core+Element+SQL Server开发校园图书管理系统(四)(上)
81 0
|
SQL Web App开发 Java
十四、.net core(.NET 6)搭建ElasticSearch(ES)系列之给ElasticSearch添加SQL插件和浏览器插件
给ES添加SQL插件的方法:下载SQL插件地址:https://github.com/NLPchina/elasticsearch-sql当前最新的是7.12版本,我的ES是7.13版本,暂且将就用一下,也许能用呢?
236 0
十四、.net core(.NET 6)搭建ElasticSearch(ES)系列之给ElasticSearch添加SQL插件和浏览器插件
|
SQL .NET 数据库
.net core 2.1-----Sql Server数据库初体验
刚开始接触asp.net core,在学习的过程中遇到了一些小问题,在这里记录一下! 在我们项目的开发过程中,肯定会和数据库打交道,所以我尝试了一下用asp.net core链接数据库,并读取表中的数据(当然你必须保证有能访问的sql server数据库)! 首先,新建项目:ASP.
1283 0
|
SQL .NET Linux
用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(3)
第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 由于本文主要是讲VSCode开发等, 所以相关等一些angular/.
1451 0
|
SQL Web App开发 Linux
用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)
最近使用vscode比较多. 学习了一下如何在mac上使用vscode开发asp.netcore项目. 这里是我写的关于vscode的一篇文章:  https://www.cnblogs.com/cgzl/p/8450179.
1650 0
|
4天前
|
SQL IDE Java
Java连接SQL Server数据库的详细操作流程
Java连接SQL Server数据库的详细操作流程