查缺补漏系统学习 EF Core 6 - 原始 SQL 查询

推荐关注「码侠江湖」星标,时刻不忘江湖事

这是 EF Core 系列的第五篇文章,上一篇文章盘点了 EF Core 中的几种数据查询方式。

但是有有时候,我们可能无法用标准的 LINQ 方法完成查询任务。

或者编译后的 LINQ 查询,没有我们想要的那么高效;又或者我们想要调用一个存储过程。

这些情况下,我们希望可以编写原始 SQL 语句,让 EF Core 去执行。

因此,这篇文章就简要的讲一讲如何在 EF Core 中使用原始 SQL 语句进行查询。

点击上方或后方蓝字,阅读 EF Core 系列合集

ad3127b697bef6a9395571b2f7662d7d.png

FromSqlRaw

让我们来看一个简单的示例:

var account = 
  _context.Accounts
    .FromSqlRaw(@"SELECT * FROM Account WHERE Name = {0}", "Zilor")
    .FirstOrDefault();

FromSqlRaw 方法允许我们将原始 SQL 语句,添加到 EF Core 查询中。

还可以执行存储过程:

var account = 
  _context.Accounts
    .FromSqlRaw("EXECUTE dbo.MyCustomProcedure")
    .ToList();

需要注意的是 FromSqlRaw 方法有一些限制:

  • 结果中的列名,必须与属性被映射到的列名相匹配

  • 查询必须为实体或查询类型的所有属性返回数据

  • SQL 查询不能包含导航关系,但我们总是可以把 FromSqlRawInclude 方法结合起来。

如果想在查询中包含导航关系,可以这样做:

var account = 
  _context.Accounts
    .FromSqlRaw("SELECT * FROM Account WHERE Name = {0}", "Zilor")
    .Include(e => e.AccountSubjects)
    .FirstOrDefault();

ExecuteSqlRaw

FromSqlRaw 可以执行原始 SQL 语句查询,但不能执行插入、删除、更新等 SQL 语句,这需要使用 ExecuteSqlRaw 方法实现,比如这样:

var rowsAffected = 
  _context.Database
    .ExecuteSqlRaw(
    @"UPDATE Account
    SET Age = {0} 
    WHERE Name = {1}",
    20, "Zilor");

这个方法会返回受影响的行数,无论是从数据库中更新、插入还是删除记录,行为都一样。

需要注意是,这里我们使用了 Database 属性,来调用 ExecuteSqlRaw 方法

而在之前的例子中,我们都是使用 Account 属性,来调用 FromSqlRaw 方法。

另一件重要的事情是,我们在 FromSqlRawExecuteSqlRaw 方法中,都使用了查询字符串插值功能。

它允许我们在查询字符串中放置一个变量名,然后 EF Core 会检查这些参数。

检查参数的目的,是为了以防止 SQL 注入攻击。

因此,我们不能在 EF Core 原始 SQL 查询方法之外,使用字符串插值组装 SQL 语句。因为,这样会失去 SQL 参数注入攻击的检测。

虽然直接执行 SQL 语句的方式比较直接,但缺点就是在代码中直接操作数据库的方式,不符合 ORM 的编程模式与思想。

如果我们直接操作数据库表,那么就无法利用 EF Core 强类型的特性。

如果实体模型发生改变,那么必须手动变更 SQL 语句。

而且如果调用了一些某些数据库特有的语法和函数,那么一旦程序迁移到其他数据库,就可能需要重新编写 SQL 语句。

这样也就无法利用 EF Core 强大的 SQL 翻译机制,来屏蔽不同底层数据库的差异。

所以,在能不用的情况下,最好不要使用执行原生 SQL 语句的功能。

重新加载

假设我们有一个已经加载的实体,然后使用 ExecuteSqlRaw 方法,对数据库中的实体做了一些修改,那此时我们加载的实体肯定是过时。

比如这样:

var accountForUpdate =
  _context.Accounts
    .FirstOrDefault(s => s.Name.Equals("Zilor"));

var rowsAffected =
  _context.Database
    .ExecuteSqlRaw(
    @"UPDATE Account
    SET Age = {0}
    WHERE Name = {1}",
    22, accountForUpdate.Name);

只要我们执行这个查询,数据库中的 Age 就会变成 22

accountForUpdate 对象中的 Age 属性则不会改变,尽管它在数据库中已经被改变了。

所以,现在的问题是,如果我们想让它在执行 ExecuteSqlRaw 方法后,实体对象的值随之改变,该怎么办?。

其实很简单,我们只需要在 SQL 语句执行完成后,使用 Reload 方法重新加载这个实体即可:

_context.Entry(accountForUpdate).Reload();

小结

这篇文章主要讲了 EF Core 的原始 SQL 语句查询,下篇文章讲继续讲述 EF Core 的数据修改。

更多精彩内容,请关注我▼▼

 
 

d57f0aa5902b080818a6a69a719e0367.gif

如果喜欢我的文章,那么

在看和转发是对我最大的支持!

(戳下面蓝字阅读)

cfb043d8f4ee97c7a651363729800a5a.png

推荐关注微信公众号:码侠江湖

                        e8b9f958f0896b793d9b75c2038278ab.png觉得不错,点个在看再走哟

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EF6 是 Entity Framework 6 的简称,它是微软开发的一种对象关系映射(ORM)工具。T-SQL 是 Transact-SQL 的简称,是一种用于 SQL Server 数据库查询语言。 在 EF6 查询性能和 T-SQL 对比方面,有以下几点需要考虑: 1. 执行计划:EF6 会将 LINQ 查询转换为相应的 SQL 查询语句,然后由数据库服务器执行。而 T-SQL 直接在数据库服务器上执行,因此在执行计划的生成和优化方面,T-SQL 通常更加高效。 2. 数据库适应性:T-SQL 可以充分利用数据库的特性和优化策略,如索引、分区等。而 EF6 在生成 SQL 查询语句时,可能无法充分利用数据库的特性,导致性能较低。 3. 缓存机制:EF6 提供了查询结果的缓存机制,可以在一定程度上提高查询性能。而 T-SQL 没有内置的缓存机制,需要手动实现。 4. 查询表达能力:EF6 使用 LINQ 查询语法,提供了强类型的查询表达能力,可以更加直观和灵活地进行查询。而 T-SQL查询表达能力相对较弱,需要手动编写 SQL 查询语句。 综上所述,EF6 在查询性能方面可能不如 T-SQL,特别是在复杂查询和大数据量的情况下。如果对性能要求较高,可以考虑直接使用 T-SQL 编写查询语句。但是,EF6 提供了更方便和灵活的开发方式,并且在简单查询和开发效率方面具有优势。所以,在选择使用 EF6 还是 T-SQL 时,需要根据具体场景和需求进行权衡。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值