设为首页 收藏本站
查看: 1147|回复: 0

[经验分享] EntityFramework Core Raw SQL

[复制链接]

尚未签到

发表于 2017-7-14 14:02:31 | 显示全部楼层 |阅读模式
前言
  本节我们来讲讲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();
}
}
DSC0000.gif

  下面我们来看看存储过程。



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();
}
  我们通过开启调试,可以清晰看到执行的存储过程。
DSC0001.png

  通过如上我们知道参数化查询有两种形式,下面我们再来看看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();
}
DSC0002.png

  好吧,明确告诉我们对于存储过程是不支持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();
}
  结果出乎意料的出现语法错误:
DSC0003.png

  通过SQL Server Profiler查看发送的SQL语句如下:
DSC0004.png

  这能不错么,官网给的示例也是和上述一样,如下:
DSC0005.png

  只是按照和他一样的搬过来了,未曾想太多,还是粗心大意了,想了好一会,按照我们正常调用表值函数即可,我们需要用括号括起来才行,如下:



        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如下才是正确的。
DSC0006.png

  好了,到了这里关于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;
}
DSC0007.gif


总结
  我们本节讲述了EF Core中的原始查询,相比较之前EF版本的原始查询使用更加灵活了一点,但是缺陷还是展露无遗,依然只能查出所有的列且必须匹配,同时呢,若我们想执行事务,目前还不支持底层的TranscationScope仅仅支持BeginTranscation。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-393771-1-1.html 上篇帖子: EntityFramework监控sql和EntityFramework中的事务 下篇帖子: 《MSSQL2008技术内幕:T-SQL语言基础》读书笔记(上)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表