EF Core 2.2.6调用多表关联存储过程并获取返回值问题
解决方案
因为你需要的自定义对象对应多表联合数据,且EF Core 2.2.6不支持直接将非DbSet实体与FromSql结合,所以可以通过ADO.NET结合EF上下文的数据库连接来实现,同时获取存储过程的返回值。
步骤1:定义自定义对象
先确保你已经定义了目标自定义对象(字段需与存储过程返回的列一一对应):
public class RequiredObject { public int Id { get; set; } public string ProductName { get; set; } public string CategoryName { get; set; } // 来自第二张表 public decimal Price { get; set; } // 来自第三张表 // 其他字段根据存储过程返回结果补充 }
步骤2:调用存储过程并映射结果
通过EF上下文获取数据库连接,手动执行存储过程、读取结果并映射到自定义对象,同时获取返回值:
SqlParameter returnVal = new SqlParameter("@return", SqlDbType.Int) { Direction = ParameterDirection.ReturnValue }; List<RequiredObject> resultList = new List<RequiredObject>(); int? procedureReturnValue = null; using (var context = new Context()) { var connection = context.Database.GetDbConnection(); try { connection.Open(); using (var command = connection.CreateCommand()) { // 配置存储过程命令 command.CommandText = "SP_Name"; command.CommandType = CommandType.StoredProcedure; // 添加返回值参数 command.Parameters.Add(returnVal); // 若存储过程需要其他输入/输出参数,在此添加 // command.Parameters.Add(new SqlParameter("@InputParam", "测试参数")); // 执行并读取结果 using (var reader = command.ExecuteReader()) { while (reader.Read()) { var obj = new RequiredObject { Id = reader.GetInt32(reader.GetOrdinal("Id")), ProductName = reader.GetString(reader.GetOrdinal("ProductName")), CategoryName = reader.GetString(reader.GetOrdinal("CategoryName")), Price = reader.GetDecimal(reader.GetOrdinal("Price")) // 其他字段按顺序映射 }; resultList.Add(obj); } } // 读取返回值(必须在读取完结果集之后) procedureReturnValue = (int)returnVal.Value; } } finally { if (connection.State == ConnectionState.Open) { connection.Close(); } } } // resultList为存储过程返回的自定义对象集合,procedureReturnValue为存储过程返回值
关键注意事项
- 存储过程的返回值必须在读取完
SqlDataReader之后才能获取,因为返回值要等结果集全部返回后才会赋值。 - 映射字段时,确保
reader.GetOrdinal("列名")中的列名与存储过程返回的列名完全一致,大小写敏感。 - 若需异步执行,可替换为
OpenAsync()、ExecuteReaderAsync()等异步方法,并添加await关键字。
内容的提问来源于stack exchange,提问作者Kirill Fi
相关产品推荐
相关产品推荐

