EF Core 执行原生SQL语句


前言

为什么要写原生SQL语句?

  1. 尽管EF Core已经非常强大,但是任然存在着无法被写成标准EF Core调用方法的SQL语句,少数情况下任然需要写原生SQL。
  2. 存在问题:可能无法跨数据库操作。

一、执行查询(返回数据)

1) 使用 FromSqlRaw或 FromSqlInterpolated 方法,适用于 DbSet,返回实体集合。

示例:查询数据(建议使用FromSqlInterpolated,防止SQL注入

var blogs = context.Blogs
    .FromSqlRaw("SELECT * FROM Blogs WHERE Rating > {0}", 3)
    .ToList();

// 或使用插值字符串(参数化,防注入)
var rating = 3;
var blogsSafe = context.Blogs
    .FromSqlInterpolated($"SELECT * FROM Blogs WHERE Rating > {rating}")
    .ToList();

2)结合 LINQ 查询

var filteredBlogs = context.Blogs
    .FromSqlInterpolated("SELECT * FROM Blogs")
    .Where(b => b.Url.Contains("dotnet"))
    .OrderBy(b => b.Rating)
    .ToList();

3)执行任意原生SQL查询语句(使用ADO.Net)

DbConnection conn=dbContext.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
{ 
    conn.Open();
}
using (var cmd = conn.CreateCommand())
{
    cmd.CommandText = "select Title,Content from T_Articles where Title like '%反反复复%'";
    using (var reader = await cmd.ExecuteReaderAsync())
    {
        while (await reader.ReadAsync())
        {
            string title = reader.GetString(0);
            string content= reader.GetString(1);
            Console.WriteLine(title+","+content);
        }
    }
    
}

二、执行非查询操作(增删改)

1)使用 ExecuteSqlRaw() 或 ExecuteSqlInterpolated() 、ExecuteSqlInterpolatedAsync()方法,返回受影响的行数。

示例:更新数据

var rowsAffected = context.Database.ExecuteSqlRaw(
    "UPDATE Blogs SET Rating = 5 WHERE Name LIKE '%EF Core%'");

// 参数化示例
var minRating = 3;
var rowsSafe = await context.Database.ExecuteSqlInterpolatedAsync(
    $"DELETE FROM Blogs WHERE Rating < {minRating}");

三、调用存储过程

1)执行查询存储过程

var blogs = context.Blogs
    .FromSqlRaw("EXEC GetTopRatedBlogs @p0", 5)
    .ToList();

2)执行非查询存储过程

context.Database.ExecuteSqlRaw("EXEC ArchiveOldBlogs @p0", DateTime.Now.AddYears(-1));

四、事务处理

1)确保多个 SQL 操作原子性

using (var transaction = context.Database.BeginTransaction())
{
    try
    {
        context.Database.ExecuteSqlRaw("UPDATE Blogs SET Rating = 5 WHERE BlogId = 1");
        context.Database.ExecuteSqlRaw("DELETE FROM Blogs WHERE BlogId = 2");
        transaction.Commit();
    }
    catch
    {
        transaction.Rollback();
    }
}

五、原生 SQL 查询的注意事项

  1. 参数化查询:始终使用参数化输入(如 {0} 或插值语法)避免 SQL 注入。
  2. 列匹配:查询返回的列名必须与实体属性名匹配,或通过 AS 别名映射。
  3. 跟踪变更:默认跟踪实体变更,若无需跟踪可加 .AsNoTracking()。
  4. 数据库兼容性:SQL 语法需适配具体数据库(如 SQL Server 和 SQLite 的差异)。
  5. 性能:仅在必要时使用原生 SQL,优先选择 LINQ 以保证类型安全和可维护性。

总结

一般情况下Linq操作就足够了,尽量不要用原生SQL。

  1. EF Core 的原生 SQL 方法适用于特定场景,但需谨慎使用以确保安全性和可维护性。优先考虑 LINQ,复杂场景再选择原生 SQL
  2. 非查询SQL用ExecuteSqlInterpolatedAsync()
  3. 针对实体的SQL查询用FromSqlInterpolated()
  4. 复杂SQL查询用ADO.NET的方式或者Dapper等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值