配色: 字号:
EntityFramework Core Raw SQL
2017-01-06 | 阅:  转:  |  分享 
  
EntityFrameworkCoreRawSQL



前言

本节我们来讲讲EFCore中的原始查询,目前在项目中对于简单的查询直接通过EF就可以解决,但是涉及到多表查询时为了一步到位就采用了原始查询的方式进行。下面我们一起来看看。



EntityFrameworkCoreRawSQL

基础查询(执行SQL和存储过程)



啥也不说了,拿起键盘就是干,如下:



复制代码

publicclassHomeController:Controller

{

privateIBlogRepository_blogRepository;

publicHomeController(IBlogRepositoryblogRepository)

{

_blogRepository=blogRepository;

}

publicIActionResultIndex()

{

varlist=_blogRepository.GetList();

returnOk();

}

}

复制代码

复制代码

publicclassBlogRepository:EntityBaseRepository,

IBlogRepository

{

privateEFCoreContext_efCoreContext;

publicBlogRepository(EFCoreContextefCoreContext):base(efCoreContext)

{

_efCoreContext=efCoreContext;

}



publicIEnumerableGetList()

{

variQueryTable=_efCoreContext.Set().

FromSql("selectfromBlog");

returniQueryTable.ToList();

}

}

复制代码





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



复制代码

CREATEPROCEDUREdbo.GetBlogList

AS

BEGIN

SELECTFROMdbo.Blog

END

GO

复制代码

复制代码

publicIEnumerableGetList()

{

variQueryTable=_efCoreContext.Set().

FromSql("EXECUTEdbo.GetBlogList");

returniQueryTable.ToList();

}

复制代码

参数查询



利用参数化存储过程查询。



复制代码

ALTERPROCEDURE[dbo].[GetBlogList]

@idINT

AS

BEGIN

SELECTFROMdbo.BlogWHEREId=@id

END

复制代码

结果利用FromSql就变成了如下:



复制代码

publicIEnumerableGetList()

{

varId=newSqlParameter("Id","1");

variQueryTable=_efCoreContext.Set().

FromSql("EXECdbo.GetBlogList{0}",1);

returniQueryTable.ToList();

}

复制代码

上述是利用string.format的形式来传参,我们也可以利用SqlParameter来传参,如下:



复制代码

publicIEnumerableGetList()

{

varId=newSqlParameter("Id","1");

variQueryTable=_efCoreContext.Set().

FromSql("EXECdbo.GetBlogList@id",Id);

returniQueryTable.ToList();

}

复制代码

我们通过开启调试,可以清晰看到执行的存储过程。







通过如上我们知道参数化查询有两种形式,下面我们再来看看linq查询。



linq查询



上述我们演示一直直接使用FromSql,其实在此之后我们可以继续通过linq来进行查询,如下:



复制代码

publicIEnumerableGetList()

{

varId=newSqlParameter("Id","2");

variQueryTable=_efCoreContext.Set().

FromSql("EXECdbo.GetBlogList@id",Id).Where(d=>d.Name=="efcore2");

returniQueryTable.ToList();

}

复制代码

之前我们映射了Blog和Post之间的关系,这里我们只能查询出Blog表的数据,通过对上述linq的讲解,我们完全可以通过inlcude来显式加载Post表数据,如下:



复制代码

publicIEnumerableGetList()

{

varId=newSqlParameter("Id","2");

variQueryTable=_efCoreContext.Set().

FromSql("EXECdbo.GetBlogList@id",Id).Include(d=>d.Posts);

returniQueryTable.ToList();

}

复制代码





好吧,明确告诉我们对于存储过程是不支持Inlude操作的,所以要想Include我们只能进行简单的查询,如下:



复制代码

publicIEnumerableGetList()

{

variQueryTable=_efCoreContext.Set().

FromSql("selectfromblog").Include(d=>d.Posts);

returniQueryTable.ToList();

}

复制代码

查找官网资料时发现居然对表值函数(TVF)是可以Include的,创建内嵌表值函数如下:



复制代码

USE[EFCoreDb]

GO



IFOBJECT_ID(''dbo.GetBlog'')ISNOTNULL

DROPFUNCTIONdbo.GetBlog;

GO



CREATEFUNCTIONdbo.GetBlog

(@NameVARCHAR(max))RETURNSTABLEWITHSCHEMABINDING

AS

RETURN

SELECTId,Name,UrlFROMdbo.BlogWHEREName=@Name

GO

复制代码

调用如下:



复制代码

publicIEnumerableGetList()

{

varname="efcore2";

variQueryTable=_efCoreContext.Set().

FromSql("selectfrom[dbo].[GetBlog]{0}",name).Include(d=>d.Posts);

returniQueryTable.ToList();

}

复制代码

结果出乎意料的出现语法错误:







通过SQLServerProfiler查看发送的SQL语句如下:







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







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



复制代码

publicIEnumerableGetList()

{

varname="efcore2";

variQueryTable=_efCoreContext.Set().

FromSql("selectfrom[dbo].[GetBlog]({0})",name).Include(d=>d.Posts);

returniQueryTawww.tt951.comble.ToList();

}

复制代码

上述将[dbo.GetBlog]和({0})隔开和挨着都可以。这个时候才不会出现语法错误。执行的SQL如下才是正确的。







好了,到了这里关于EFCore中原始查询我们就告一段落了,其中还有一个知识点未谈及到,在EFCore我们可以直接通过底层的ADO.NET来进行查询,我们来看下:



底层ADO.NET查询



复制代码

publicIEnumerableGetList()

{

varlist=newList();

using(varconnection=_efCoreContext.Database.GetDbConnection())

{

connection.Open();



using(varcommand=connection.CreateCommand())

{

command.CommandText="SELECTFROMdbo.Blog";



using(SqlDataReaderreader=command.ExecuteReader()asSqlDataReader)

{

while(reader.Read())

{

varblog=newBlog();

blog.Id=Convert.ToInt32(reader["Id"]);

blog.Name=reader["Name"].ToString();

blog.Url=reader["Url"].ToString();

list.Add(blog);

}

}

}

}

returnlist;

}

复制代码





总结

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

献花(0)
+1
(本文系thedust79首藏)