如何在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的无键实体,属性名需与存储过程返回列名匹配:
- 在DbContext中注册无键实体:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 为你的泛型结果类注册无键实体,若有多个可批量处理 modelBuilder.Entity<UserProcedureResult>().HasNoKey(); }
- 泛型执行方法:
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
相关产品推荐
相关产品推荐

