EFCore之执行原生SQL语句
EFCore通过 LINQ 语法为我们提供了非常便利的方式来操作数据库。当有些业务逻辑较复杂而不能使用 LINQ 来查询时,可以使用原生 SQL 查询。或者使用 LINQ 查询导致 SQL 查询效率低下时,也可以使用原生 SQL 查询。EFCore为我们提供以下几种方式来执行原生SQL语句此种方式一定要确保参数 endDate 是经过验证的,否则会产生SQL注入的风险。可以通过使用形参占位符并提供
EFCore通过 LINQ 语法为我们提供了非常便利的方式来操作数据库。
当有些业务逻辑较复杂而不能使用 LINQ 来查询时,可以使用原生 SQL 查询。
或者使用 LINQ 查询导致 SQL 查询效率低下时,也可以使用原生 SQL 查询。
EFCore为我们提供以下几种方式来执行原生SQL语句
功能 | 方法签名 |
---|---|
查询 | IQueryable<TEntity> FromSqlRaw<TEntity>(string sql, params object[] parameters) |
IQueryable<TEntity> FromSqlInterpolated<TEntity>(FormattableString sql) | |
增删改 | int ExecuteSqlRaw(string sql, params object[] parameters) |
int ExecuteSqlInterpolated(this DatabaseFacade databaseFacade, FormattableString sql) | |
增删改(异步) | Task<int> ExecuteSqlRawAsync(string sql, CancellationToken cancellationToken = default(CancellationToken)) |
Task<int> ExecuteSqlInterpolatedAsync(this DatabaseFacade databaseFacade, FormattableString sql, CancellationToken cancellationToken = default(CancellationToken)) |
- FromSqlRaw
_dbContext.ExceptionLog.FromSqlRaw($"SELECT * FROM ExceptionLog WHERE Logged<='{endDate}'")
//变量endDate为2022-06-27 13:41:25时生成的SQL语句如下:
SELECT * FROM log.ExceptionLog WHERE Logged<='2022-06-27 13:41:25'
此种方式一定要确保参数 endDate 是经过验证的,否则会产生SQL注入的风险。
可以通过使用形参占位符并提供额外的实参的方式,EFCore会帮我们把参数包装成DbParameter,从而来避免产生SQL注入的风险。
_dbContext.ExceptionLog.FromSqlRaw("SELECT * FROM ExceptionLog WHERE Logged<={0}",endDate)
//生成的SQL语句如下,{0}占位符会包装成参数@p0
SELECT * FROM log.ExceptionLog WHERE Logged<=@p0
如果你非得想使用字符串内插的方式,那么EFCore也很贴心,为我们提供了以下方法
- FromSqlInterpolated
_dbContext.ExceptionLog.FromSqlInterpolated($"SELECT * FROM ExceptionLog WHERE Logged<={endDate}")
//生成的SQL语句如下,{endDate}内插字符串变量会被包装成参数@p0
SELECT * FROM log.ExceptionLog WHERE Logged<=@p0
此种方式EFCore会自动把内插变量包装成DbParameter来实现参数化查询,既满足了我们使用内插字符串的需求,又实现了抵御 SQL 注入攻击,赞
不过EFCore的这个原生查询也有一定的缺陷,就是查询语句返回的字段列表要和实体类中属性列表保持一致,换句话说,实体类中的所有属性都要在查询结果集中包含,否则就会提示在结果集中缺少某个字段的错误,如下:
"The required column 'XXX' was not present in the results of a 'FromSql' operation."
比如某些场景我就是想要查询某些字段,总不能定义一堆的DTO吧,不知道后面微软团队会不会优化这个。
所以,如果有类似场景需求,还是用Dapper吧。。。
更多推荐
所有评论(0)