EF Core 2.1 Raw SQL Queries (转自MSDN)
Entity Framework Core allows you to drop down to raw SQL queries when working with a relational database. This can be useful if the query you want to perform can't be expressed using LINQ, or if using a LINQ query is resulting in inefficient SQL being sent to the database. Raw SQL queries can return entity types or, starting with EF Core 2.1, query types that are part of your model.
Tip
You can view this article's sample on GitHub.
Limitations
There are a few limitations to be aware of when using raw SQL queries:
- The SQL query must return data for all properties of the entity or query type.
- The column names in the result set must match the column names that properties are mapped to. Note this is different from EF6 where property/column mapping was ignored for raw SQL queries and result set column names had to match the property names.
- The SQL query cannot contain related data. However, in many cases you can compose on top of the query using the Include operator to return related data (see Including related data).
- SELECT statements passed to this method should generally be composable: If EF Core needs to evaluate additional query operators on the server (for example, to translate LINQ operators applied after FromSql), the supplied SQL will be treated as a subquery. This means that the SQL passed should not contain any characters or options that are not valid on a subquery, such as:
- a trailing semicolon
- On SQL Server, a trailing query-level hint (for example, OPTION (HASH JOIN))
- On SQL Server, an ORDER BY clause that is not accompanied of TOP 100 PERCENT in the SELECT clause
- SQL statements other than SELECT are recognized automatically as non-composable. As a consequence, the full results of stored procedures are always returned to the client and any LINQ operators applied after FromSql are evaluated in-memory.
Basic raw SQL queries
You can use the FromSql extension method to begin a LINQ query based on a raw SQL query
var blogs = context.Blogs
.FromSql("SELECT * FROM dbo.Blogs")
.ToList();
Raw SQL queries can be used to execute a stored procedure.
var blogs = context.Blogs
.FromSql("EXECUTE dbo.GetMostPopularBlogs")
.ToList();
Use SqlParameter instance to specify the value of IN or OUT parameters to execute a stored procedure as below:
int totalRowCount = default(int);
var paramLanguageCode = new SqlParameter("@languageCode", languageCode);
var paramCurrentPage = new SqlParameter("@currentPage", currentPage);
var paramPageSize = new SqlParameter("@pageSize", pageSize);
var paramOutTotalRowCount = new SqlParameter("@totalRowCount", totalRowCount)
{
Direction = ParameterDirection.Output
};
//var paramOutTotalRowCount = new SqlParameter()
//{
// ParameterName = "@totalRowCount",
// Direction = ParameterDirection.Output,
// SqlDbType = SqlDbType.Int
//};
//var parameterQuestionaryCode = new SqlParameter()
//{
// ParameterName = "@questionaryCode",
// SqlDbType = SqlDbType.NVarChar,
// Direction = ParameterDirection.Output,
// Size = 50 //注意如果是SqlDbType.NVarChar的Output参数,记得还要定义Size的大小,否者执行的时候会报错
//};
var categoriesView = context.SP_GetCategoriesViewInPage.FromSql("EXEC [MD].[SP_GetCategoriesViewInPage] @languageCode, @currentPage, @pageSize, @totalRowCount OUT", paramLanguageCode, paramCurrentPage, paramPageSize, paramOutTotalRowCount).ToList();
totalRowCount = Convert.ToInt32(paramOutTotalRowCount.Value);
同样IN和OUT参数也可以用于执行DbContext.Database.ExecuteSqlCommand方法,来返回存储过程的OUT参数值,如下所示:
int totalRowCount = default(int);
var paramLanguageCode = new SqlParameter("@languageCode", languageCode);
var paramCurrentPage = new SqlParameter("@currentPage", currentPage);
var paramPageSize = new SqlParameter("@pageSize", pageSize);
var paramOutTotalRowCount = new SqlParameter("@totalRowCount", totalRowCount)
{
Direction = ParameterDirection.Output
};
//var paramOutTotalRowCount = new SqlParameter()
//{
// ParameterName = "@totalRowCount",
// Direction = ParameterDirection.Output,
// SqlDbType = SqlDbType.Int
//};
//var parameterQuestionaryCode = new SqlParameter()
//{
// ParameterName = "@questionaryCode",
// SqlDbType = SqlDbType.NVarChar,
// Direction = ParameterDirection.Output,
// Size = 50 //注意如果是SqlDbType.NVarChar的Output参数,记得还要定义Size的大小,否者执行的时候会报错
//};
context.Database.ExecuteSqlCommand("EXEC [MD].[SP_GetCategoriesViewInPage] @languageCode, @currentPage, @pageSize, @totalRowCount OUT", paramLanguageCode, paramCurrentPage, paramPageSize, paramOutTotalRowCount);
totalRowCount = Convert.ToInt32(paramOutTotalRowCount.Value);
下面代码展示了如何创建一个SQL Server数据库DECIMAL(8,4)类型的SqlParameter参数@Price
private static void AddSqlParameter(SqlCommand command)
{
SqlParameter parameter = new SqlParameter("@Price", SqlDbType.Decimal);
parameter.Value = 3.1416;
parameter.Precision = ;
parameter.Scale = ; command.Parameters.Add(parameter);
}
更多关于SqlParameter的信息,请参阅"SqlParameter Class"
Passing parameters
As with any API that accepts SQL, it is important to parameterize any user input to protect against a SQL injection attack. You can include parameter placeholders in the SQL query string and then supply parameter values as additional arguments. Any parameter values you supply will automatically be converted to a DbParameter.
The following example passes a single parameter to a stored procedure. While this may look like String.Format syntax, the supplied value is wrapped in a parameter and the generated parameter name inserted where the {0} placeholder was specified.
var user = "johndoe"; var blogs = context.Blogs
.FromSql("EXECUTE dbo.GetMostPopularBlogsForUser {0}", user)
.ToList();
This is the same query but using string interpolation syntax, which is supported in EF Core 2.0 and above:
var user = "johndoe"; var blogs = context.Blogs
.FromSql($"EXECUTE dbo.GetMostPopularBlogsForUser {user}")
.ToList();
You can also construct a DbParameter and supply it as a parameter value. This allows you to use named parameters in the SQL query string
var user = new SqlParameter("user", "johndoe");
var blogs = context.Blogs
.FromSql("EXECUTE dbo.GetMostPopularBlogsForUser @user", user)
.ToList();
Composing with LINQ
If the SQL query can be composed on in the database, then you can compose on top of the initial raw SQL query using LINQ operators. SQL queries that can be composed on being with the SELECT keyword.
The following example uses a raw SQL query that selects from a Table-Valued Function (TVF) and then composes on it using LINQ to perform filtering and sorting.
var searchTerm = ".NET"; var blogs = context.Blogs
.FromSql($"SELECT * FROM dbo.SearchBlogs({searchTerm})")
.Where(b => b.Rating > )
.OrderByDescending(b => b.Rating)
.ToList();
Including related data
Composing with LINQ operators can be used to include related data in the query.
var searchTerm = ".NET"; var blogs = context.Blogs
.FromSql($"SELECT * FROM dbo.SearchBlogs({searchTerm})")
.Include(b => b.Posts)
.ToList();
Warning
Always use parameterization for raw SQL queries: APIs that accept a raw SQL string such as FromSql and ExecuteSqlCommand allow values to be easily passed as parameters. In addition to validating user input, always use parameterization for any values used in a raw SQL query/command. If you are using string concatenation to dynamically build any part of the query string then you are responsible for validating any input to protect against SQL injection attacks.
EF Core 3.0更新
注意在EF Core 3.0中,FromSql方法和ExecuteSqlCommand方法都已经过时,请使用FromSqlRaw方法和ExecuteSqlRaw方法进行替代
参考文献:
Working with Stored Procedure in Entity Framework Core
EF Core 2.1 Raw SQL Queries (转自MSDN)的更多相关文章
- EF: Raw SQL Queries
Raw SQL Queries Entity Framework allows you to query using LINQ with your entity classes. However, t ...
- Executing Raw SQL Queries using Entity Framework
原文 Executing Raw SQL Queries using Entity Framework While working with Entity Framework developers m ...
- 在.NET Core类库中使用EF Core迁移数据库到SQL Server
前言 如果大家刚使用EntityFramework Core作为ORM框架的话,想必都会遇到数据库迁移的一些问题. 起初我是在ASP.NET Core的Web项目中进行的,但后来发现放在此处并不是很合 ...
- EF core 学习 执行原生sql语句 之ExecuteReader 和ExecuteScalar
通过ef core 源码分析 Microsoft.EntityFrameworkCore.Storage.RelationalCommandExtensions类中有相应的方法 为此得到相应的结果: ...
- EF Core中,通过实体类向SQL Server数据库表中插入数据后,实体对象是如何得到数据库表中的默认值的
我们使用EF Core的实体类向SQL Server数据库表中插入数据后,如果数据库表中有自增列或默认值列,那么EF Core的实体对象也会返回插入到数据库表中的默认值. 下面我们通过例子来展示,EF ...
- EntityFramework Core技术线路(EF7已经更名为EF Core,并于2016年6月底发布)
官方文档英文地址:https://github.com/aspnet/EntityFramework/wiki/Roadmap 历经延期和更名,新版本的实体框架终于要和大家见面了,虽然还有点害羞.请大 ...
- [转]How to get return values and output values from a stored procedure with EF Core?
本文转自:https://stackoverflow.com/questions/43935345/how-to-get-return-values-and-output-values-from-a- ...
- [转]EntityFramework Core技术线路(EF7已经更名为EF Core,并于2016年6月底发布)
本文转自:http://www.cnblogs.com/VolcanoCloud/p/5572408.html 官方文档英文地址:https://github.com/aspnet/EntityFra ...
- EF core 性能调优
Entity Framework Core performance tuning – a worked example Last Updated: February 25, 2019 | Create ...
随机推荐
- logback配置文件---logback.xml详解
一.参考文档 1.官方文档 http://logback.qos.ch/documentation.html 2.博客文档 http://www.cnblogs.com/warking/p/57103 ...
- 第8课 网络数据读取测试-TinyWebDB
TinyWebDB是在线小型数据库,通过它的使用,可以将数据保存在网络,实现排行榜等功能. 实现功能:读入数据并保存,读出数据并显示. 1.组件设计 TinyWebDB1:非可视化,借用网 ...
- Hadoop完全分布分布式配置
1.准备三台虚拟机.安装Ubuntu操作系统,具体过程省略 2.三台虚拟机上分别安装Java环境,具体过程省略(保证三者的Java路径一致) 3.三台机器分别配置ssh本机免密码登录 (1)安装ssh ...
- base64编码以及url safe base64是怎么工作的?
原文转自 http://www.yanshiba.com/archives/638 1: 为什么需要base64? ASCII码一共规定了128个字符的编码,这128个符号,范围在[0,127]之间. ...
- SpringMvc学习---基础知识考核
SpringMVC 1.SpringMVC的工作流程 流程 : 1.用户发送请求至前端控制器DispatcherServlet2.DispatcherServlet收到请求调用HandlerMappi ...
- Java实例---俄罗斯方块
代码分析 定义格子 package com.ftl.tetris; /** * 定义格子 */ import java.awt.image.BufferedImage; public class Ce ...
- 读 CSI讲义 费马小定理
费马小定理 最近在上计算机安全学选修课.. 读老师博客..现在当是写阅读笔记吧. 这里贴出老师的简书建议先看看链接先..毕竟我这些东西只是搞笑一下的.. 遵循一下这个原则… 观察 找规律 求证 首先是 ...
- PetaPoco轻量级ORM框架 - 对Database类的进行扩展,可以返回Table格式数据
一.有时我们需要将常用的功能添加到PetaPoco中的Database类中 实现方式有2种,以下以查询字段为例 1.通过扩展方式实现,此方式不改变被调用(Database)类名(只能增加方法) pub ...
- 020.2.1 system
内容:System的常用方法1.currentTimeMillis()方法(与1970年相差多少毫秒),2.Properties getProperties():获取系统属性3.Set<Str ...
- 019.2 map集合类
Map<k,v>Map:双列集合,一次存一对,键值对,类似于python的字典.共性功能:1.添加 v put(key,value) //返回key的旧值 putAll ...