EntityFramework Core 2.0执行原始查询如何防止SQL注入?
前言
接下来一段时间我们来讲讲EntityFramework Core基础,精简的内容,深入浅出,希望为想学习EntityFramework Core的童鞋提供一点帮助。
EntityFramework Core执行原始查询
在EntityFramework Core中执行原始查询我们借助FromSql来实现,如下:
using (var context = new EFCoreDbContext()) { var orders = context.Orders .FromSql("SELECT * FROM dbo.Orders") .ToList(); }
这是最简单且不带任何条件的查询方式,接下来我们看看有条件的查询我们应该如何查询,如下:
using (var context = new EFCoreDbContext()) { var parameters = new SqlParameter[] { new SqlParameter(){ ParameterName = "@p0", Value = 1, SqlDbType = System.Data.SqlDbType.Int } }; var orders = context.Orders .FromSql("SELECT * FROM dbo.Orders WHERE Id = @p0", parameters) .ToList(); }
除了以上利用参数化查询方式外,若我们还借助string.format或者C# 6.0出现的新特性字符串插值即美元符号$来查询最终生成的SQL是否仍然是以参数化查询呢,我们来看看。
using (var context = new EFCoreDbContext()) { var orders = context.Orders .FromSql($"SELECT * FROM dbo.Orders WHERE Id = {1}") .ToList(); }
由上我们看出即使利用字符串插值最终仍然翻译成参数化SQL。接下来我们再来看看字符串拼接查询方式。
using (var context = new EFCoreDbContext()) { var searchString = "Jeffcky"; var blogs = context.Blogs .FromSql("SELECT Id, Name, CreatedTime, Url, ModifiedTime FROM dbo.Blogs " + "WHERE Name = '" + searchString + "'") .ToList(); }
此时我们通过控制台打印能够看出最终生成的SQL语句是以字符串形式展示,在EntityFramework Core 2.0+上执行原始查询的APi即FromSql有重载方法,如下:
public static IQueryable<TEntity> FromSql<TEntity>([NotNullAttribute] this IQueryable<TEntity> source, [NotNullAttribute][NotParameterized] FormattableString sql) where TEntity : class;
我们利用上述FromSql重载方法传递字符串参数,同时在查询字符串中添加对数据库表操作,验证EF Core是否能防止SQL注入。
using (var context = new EFCoreDbContext()) { var searchString = "Jeffcky; DROP TABLE dbo.Blogs;"; var blogs = context.Blogs .FromSql("SELECT Id, Name, Url, CreatedTime, ModifiedTime FROM dbo.Blogs " + " WHERE Name = {0}", searchString) .ToList(); }
经过验证您会发现上述我们注入上述Blogs表的SQL语句,最终表将不会删除。我们看到当未利用重载方法进行字符串拼接,此时参数将以字符串形式展示,这种情况极易引起SQL注入问题。C# 6.0引入了字符串插值(String Interpolation),此特性能够允许C#表达式直接嵌入到字符串文本中,为运行时构建字符串提供了一个很好的方法。在EF Core 2.0特性中,对FromSql和ExecuteSqlCommand方法都添加了对插入字符串的特殊支持。此新特性的支持允许以安全的方式使用C#字符串插值。即防止在运行时动态构建SQL时可能发生SQL注入问题。
是不是到了这里就这样结束了呢?显然不是这样,接下来咱们再来看看另外一种情况,如下:
using (var context = new EFCoreDbContext()) { var author = "Jeffcky Wang"; var query = $"SELECT * FROM Blogs WHERE Name = {author}"; var blogs = context.Blogs.FromSql(query).ToList(); }
这样的语法错误显而易见,我们需要用单引号将变量包含起来才能避免语法错误,如下:
using (var context = new EFCoreDbContext()) { var author = "Jeffcky Wang"; var query = $"SELECT * FROM Blogs WHERE Name = '{author}'"; var blogs = context.Blogs.FromSql(query).ToList(); }
上述情况下,EF Core依然将执行明文字符串而不是作为变量查询并未以参数化执行。如果变量包含恶意字符串,那么EF Core将根本无法防范并保护SQL。因此,如果我们需要通过EF Core执行原始T-SQL,则应使用参数化SQL或利用FormatttableString,FromSql有两个重载,其一为通过FormatttableString可格式化字符串参数,其二为原始字符串且可传递查询参数。所以上述错误,我们可利用FormatttableString来执行,同时在利用FromSql方法查询过后我们仍可以继续进行查询,比如如下关联查询Posts表数据。
using (var context = new EFCoreDbContext()) { var searchString = "Jeffcky Wang"; FormattableString sql = $@"SELECT Id, Name, Url, CreatedTime, ModifiedTime FROM dbo.Blogs WHERE Name = {searchString}"; var blogs = context.Blogs .FromSql(sql) .Include(d => d.Posts) .ToList(); }
通过【$@】并利用FormattableString重载或者传递参数化变量来防止SQL注入问题,希望您发现EF Core 2.0中这个新特性,同时不要忘记它也用来承担更大的责任,由于SQL注入攻击,不会让我们所写代码存在漏洞。
总结
本节我们详细讲解了EF Core 2.0中执行原始查询如何防止SQL注入问题,精简的内容,简单的讲解,希望能帮助到您。我们明天再会。

为了方便大家在移动端也能看到我分享的博文,现已注册个人公众号,扫描上方左边二维码即可,欢迎大家关注,有时间会及时分享相关技术博文。
感谢花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让楼主能喝上一杯咖啡,在此谢过了!
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!
本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/CreateMyself)/欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?