You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在EF Core中调用存储过程并通过泛型类返回结果?

在Entity Framework Core中调用存储过程并返回泛型类结果

在EF Core中,原EF的Database.SqlQuery<T>方法已不再直接可用,以下是几种可行的实现方式,适配你的泛型类需求(基于IStoredProcedure接口):

首先确保你的泛型类实现了IStoredProcedure接口:

public interface IStoredProcedure
{
    string Query { get; } // 存储过程名称或执行语句
}

// 示例实现类
public class UserProcedureResult : IStoredProcedure
{
    public string Query => "GetUserList"; // 存储过程名
    public int Id { get; set; }
    public string Name { get; set; }
}

方法1:使用EF Core无键实体 + FromSqlRaw

适用于将泛型类注册为EF Core的无键实体,属性名需与存储过程返回列名匹配:

  1. 在DbContext中注册无键实体:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 为你的泛型结果类注册无键实体,若有多个可批量处理
    modelBuilder.Entity<UserProcedureResult>().HasNoKey();
}
  1. 泛型执行方法:
public IEnumerable<T> ExecuteStoredProcedure<T>(object[] sqlParameters) where T : IStoredProcedure, new()
{
    var procedure = new T();
    // 将参数转换为SqlParameter数组
    var sqlParams = sqlParameters?.Select(p => p as SqlParameter ?? new SqlParameter(p.ToString(), p))
                                ?? Array.Empty<SqlParameter>();
    
    return DataContext.Set<T>().FromSqlRaw(procedure.Query, sqlParams).ToList();
}

方法2:使用ADO.NET手动执行并映射

无需依赖EF Core实体配置,完全自定义映射逻辑:

public IEnumerable<T> ExecuteStoredProcedure<T>(object[] sqlParameters) where T : IStoredProcedure, new()
{
    var procedure = new T();
    var resultList = new List<T>();
    var propCache = typeof(T).GetProperties().ToList(); // 缓存属性提升性能

    using (var connection = DataContext.Database.GetDbConnection())
    {
        connection.Open();
        using (var command = connection.CreateCommand())
        {
            command.CommandText = procedure.Query;
            command.CommandType = CommandType.StoredProcedure;

            // 添加参数
            if (sqlParameters != null)
            {
                foreach (var param in sqlParameters)
                {
                    if (param is SqlParameter sqlParam)
                    {
                        command.Parameters.Add(sqlParam);
                    }
                    else
                    {
                        // 处理普通参数(需根据实际场景调整参数名规则)
                        var paramName = $"@param{command.Parameters.Count}";
                        command.Parameters.AddWithValue(paramName, param);
                    }
                }
            }

            // 读取并映射结果
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    var item = new T();
                    foreach (var prop in propCache)
                    {
                        if (!reader.IsDBNull(reader.GetOrdinal(prop.Name)))
                        {
                            prop.SetValue(item, reader[prop.Name]);
                        }
                    }
                    resultList.Add(item);
                }
            }
        }
    }

    return resultList;
}

方法3:使用Dapper简化映射(推荐)

Dapper能自动完成列与类属性的映射,代码更简洁,需先安装Dapper NuGet包:

public IEnumerable<T> ExecuteStoredProcedure<T>(object[] sqlParameters) where T : IStoredProcedure, new()
{
    var procedure = new T();
    var parameters = new DynamicParameters();
    
    // 添加参数
    if (sqlParameters != null)
    {
        for (int i = 0; i < sqlParameters.Length; i++)
        {
            parameters.Add($"@param{i}", sqlParameters[i]);
        }
    }

    using (var connection = DataContext.Database.GetDbConnection())
    {
        return connection.Query<T>(
            sql: procedure.Query,
            param: parameters,
            commandType: CommandType.StoredProcedure
        ).ToList();
    }
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 02:57:31