You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Entity Framework Core代码优先方法下创建存储过程并映射已有存储过程

嘿,针对你用ASP.NET Core + EF Core代码优先模式遇到的两个需求——创建新存储过程和映射已有存储过程,我给你整理了项目里常用的实用步骤和方法:

一、创建新的存储过程(Code First模式)

Code First模式下创建存储过程,最规范的方式是通过**迁移(Migrations)**来实现,这样能保证数据库Schema和代码的同步性,步骤如下:

  1. 生成空迁移文件
    在Package Manager Console(PMC)或者终端里执行命令,创建一个空的迁移类:

    # PMC命令
    Add-Migration CreateStoredProcedure_GetAllUsers
    # 终端命令
    dotnet ef migrations add CreateStoredProcedure_GetAllUsers
    
  2. 编辑迁移类的SQL逻辑
    打开生成的迁移文件,在Up方法里编写创建存储过程的SQL,同时在Down方法里编写回滚逻辑(删除存储过程):

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        // 创建获取所有用户的存储过程
        migrationBuilder.Sql(@"
            CREATE PROCEDURE GetAllUsers
            AS
            BEGIN
                SELECT Id, Name, Email, CreateTime FROM Users;
            END
        ");
    }
    
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        // 回滚时删除存储过程
        migrationBuilder.Sql("DROP PROCEDURE IF EXISTS GetAllUsers");
    }
    
  3. 应用迁移到数据库
    执行命令将迁移逻辑同步到数据库,存储过程就会被创建:

    # PMC命令
    Update-Database
    # 终端命令
    dotnet ef database update
    
二、映射已存在的存储过程到EF Core

如果数据库里已经有现成的存储过程,想要让EF Core调用它,有三种常用方式:

方式1:用FromSqlRaw/FromSqlInterpolated查询实体

如果存储过程的返回结果和你的现有实体类字段完全匹配,可以直接用这个方法查询。比如你有User实体,存储过程GetAllUsers返回的字段和User对应:

public class AppDbContext : DbContext
{
    public DbSet<User> Users { get; set; }

    // 调用存储过程获取用户列表
    public IEnumerable<User> GetAllUsers()
    {
        return Users.FromSqlRaw("EXEC GetAllUsers").ToList();
    }

    // 带参数的存储过程调用(用FromSqlInterpolated防止SQL注入)
    public User GetUserById(int userId)
    {
        return Users.FromSqlInterpolated($"EXEC GetUserById {userId}").FirstOrDefault();
    }
}

方式2:用ExecuteSqlRaw执行非查询存储过程

如果存储过程是做插入、更新、删除这类无实体返回的操作,就用这个方法:

public class AppDbContext : DbContext
{
    // 更新用户邮箱的存储过程调用
    public int UpdateUserEmail(int userId, string newEmail)
    {
        // 用参数化方式更安全,避免SQL注入
        var parameters = new[]
        {
            new SqlParameter("@UserId", userId),
            new SqlParameter("@NewEmail", newEmail)
        };
        return Database.ExecuteSqlRaw("EXEC UpdateUserEmail @UserId, @NewEmail", parameters);
    }
}

方式3:用无键实体映射自定义结果集(EF Core 3.0+)

如果存储过程返回的结果没有对应的现有实体,可以用无键实体类型来映射:

  1. 先创建一个无键实体类,对应存储过程的返回字段:
public class UserOrderSummary
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public int TotalOrders { get; set; }
    public decimal TotalSpent { get; set; }
}
  1. 在DbContext里配置这个无键实体:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserOrderSummary>()
        .HasNoKey() // 标记为无键实体
        .ToView(null); // 因为不是视图,是存储过程,所以设为null
}
  1. 调用存储过程获取结果:
public IEnumerable<UserOrderSummary> GetUserOrderSummaries()
{
    return Set<UserOrderSummary>().FromSqlRaw("EXEC GetUserOrderSummaries").ToList();
}

内容的提问来源于stack exchange,提问作者Juber

火山引擎 最新活动