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

2023-05-16

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

这是 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

如果喜欢我的文章,那么

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

(戳下面蓝字阅读)
  • ASP.NET 6 中间件系列

  • ASP.NET 最通俗易懂的依赖注入系列

  • 查缺补漏系统学习 EF Core 6  系列

  • 老子不亏是程序员的祖师爷

  • 不得不知的超精简 HTTP 协议

cfb043d8f4ee97c7a651363729800a5a.png

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查缺补漏系统学习 EF Core 6 - 原始 SQL 查询 的相关文章

  • Ruby ActiveRecord 和 sql 元组支持

    ActiveRecord 是否支持 where 子句中的元组 假设底层数据库支持 结果 where 子句看起来像这样 where name address in John 123 Main St I tried Person where n
  • 使用用户定义函数 MySql 时出错

    您好 请帮我解决这个问题 提前致谢 我在数据库中定义了这些函数 CREATE FUNCTION levenshtein s1 VARCHAR 255 s2 VARCHAR 255 RETURNS INT DETERMINISTIC BEGI
  • 多边形内的 SQL 地理点在 STIntersect 上不返回 true(但使用 Geometry 返回 true)

    我不想仅仅为了在 STIntersect 中返回 true 而将地理数据转换为几何图形 下面是 SQL 中的代码 DECLARE point GEOGRAPHY GEOGRAPHY Point 1 1 4326 DECLARE polygo
  • MySQL NOT IN 来自同一个表中的另一列

    我想运行 mysql 查询来选择表中的所有行films其中的值title该列不存在于另一列的所有值中的任何位置 collection 这是我的表格的简化版本 其中包含内容 mysql gt select from films id titl
  • 随着时间的推移累积(不重叠)——技术?

    我正在尝试找到一种更好的方法来制作水晶报告 其他人的 按组添加不重叠的时间 这显然是一个古老的问题 有没有一种技术可以得到 调整每条记录的 开始 结束 时间 以消除共同 重叠时间 亚组内 使用直接 SQL 尽管我发现我可以执行 CTE 假设
  • 默认情况下在sql日期时间列中插入null/空值

    如何在 SQL Server 中创建一个表 默认日期时间为空 而不是1900 01 01 00 00 00 000我得到了 我的意思是 如果没有插入值 则默认值应该为 null 空等 如果没有插入值 默认值应该是null empty 在表定
  • 为什么 ISNUMERIC('.') 返回 1?

    最近我在 SQL Server 中使用 ISNUMERIC 时遇到了一个问题 导致找到了这段代码 SELECT ISNUMERIC 这会返回 1 如 true 所示 难道不应该像 false 一样返回 0 吗 See Numeric 损坏了
  • 如何在Word 2010中从SQL数据库检索数据?

    我想用 MS SQL 数据库中的数据填充 Word 文档 这可能吗 如果可能的话 如何实现 我过去曾通过多种方式做到这一点 这取决于用户是从 Microsoft Word 外部还是从 Microsoft Word 内部启动操作 From I
  • 仅选择 Varchar 列中的数字[重复]

    这个问题在这里已经有答案了 在 SQL Server 2008 R2 中 我在 varchar 12 列中有一些数据 它看起来像这样 Data 1234 1765 34566 123 SDRMH HJG434 我想从所有包含 的行中删除 并
  • Rails 中 WHERE 子句中的 ALL 运算符

    关联关系如下图所示 InstructorStudent has many fees Fee belongs to instructor student 我想要获得在所有给定数组中具有每月详细信息的指导学生 如果其中任何一个中不存在每月详细信
  • 一张表中按最大日期过滤重复行的 SQL 查询

    我有一个 SQL 数据库 persons 它具有基于 IDNum 列的重复条目 我需要查询条目并仅根据最新创建日期显示行或重复条目 这是查询 SELECT IDNum PersonPGUID CreatedDateTime FirstNam
  • postgresql 选择不同的最新记录

    我有一个像这样的表 id fkey srno remark date 1 A001 1 2 A001 2 3 A002 1 4 A003 1 5 A002 2 我想要基于 max srno 的不同最新记录 例如 2 A001 2 4 A00
  • PostgreSQL 和锁定

    希望一些比我更聪明的 DBA 可以帮助我找到一个好的解决方案来完成我需要做的事情 为了便于讨论 我们假设我有一个名为 work 的表 其中包含一些列 其中一列表示给定客户端对该行工作的所有权 场景是 我将连接 2 个客户端并轮询表以查找要完
  • SQL中如何识别字符串的第一个字符是数字还是字符

    我需要将数据中的第一个字符识别为 SQL Server 中的数字或字符 我对此比较陌生 我不知道从哪里开始 但这是我到目前为止所做的事情 我的数据看起来像这样 TypeDep Transfer From 4Z2 Transfer From
  • 使用 SQL 完全复制 postgres 表

    免责声明 这个问题和栈溢出问题类似here https stackoverflow com questions 198141 copy a table including indexes in postgres 但这些答案都不适用于我的问题
  • 如何检查一个值是否已经存在以避免重复?

    我有一个 URL 表 但我不想要任何重复的 URL 如何使用 PHP MySQL 检查给定 URL 是否已在表中 如果您不想重复 可以执行以下操作 添加唯一性约束 use REPLACE http dev mysql com doc ref
  • MySQL 正在将我的时间戳值转换为 0000-00-00

    我是 PHP 新手 目前仍在学习中 我认为我的注册表有问题 username password email全部成功插入MySQL registered and last seen不要 我以为我正在使用getTimestamp 错了 但它呼应
  • 如何在审计触发器中使用system_user但仍使用连接池?

    我想做以下两件事 在我的数据库表上使用审计触发器来识别哪个用户更新了什么 使用连接池来提高性能 对于 1 我在数据库触发器中使用 system user 来识别进行更改的用户 但这阻止我执行需要通用连接字符串的 2 有没有一种方法可以让我充
  • SQL Server 2008 R2 内连接无法匹配 varchar 字段,因为它包含特殊字符

    我们正在将 Microsoft SQL Server 2008 R2 用于我们的经典 ASP 应用程序之一 我们有两张表 TableA TableB TableA有以下列 InstName varchar 1024 TableB有这些列 I
  • Entity Framework 6 多对多想要插入重复行

    不应该这么难 我准备放弃EF了 我的模型有周刊版本 每个版本可以有许多分类广告 每个分类可以出现在一个或多个版本中 我的模型 public class Classifieds Key DatabaseGenerated DatabaseGe

随机推荐