调用返回空结果的存储过程时.FromSql报错的替代方案
问题根因
EF Core 的 FromSqlRaw 方法要求执行的SQL或存储过程必须返回与目标实体属性结构完全匹配的结果集,哪怕没有符合条件的数据,也不能完全不返回结果集。你当前的存储过程在 @TotalCount = 0 时没有任何返回,EF 无法解析到实体对应的列信息,因此抛出列不存在的异常。
解决方案
方案1:修改存储过程(优先推荐)
无需修改C#调用代码,仅调整存储过程逻辑,保证无论是否有数据都返回结构一致的结果集即可:
IF @TotalCount > 0 BEGIN SELECT CompletedPercentage, Title, Code -- 其余查询列保持不变 OFFSET @SkipResults ROWS FETCH NEXT @PageSize ROWS ONLY END ELSE BEGIN -- 返回结构匹配的空结果集 SELECT CAST(0 AS INT) AS CompletedPercentage, CAST('' AS VARCHAR(MAX)) AS Title, CAST('' AS VARCHAR(MAX)) AS Code WHERE 1 = 2 END
调整后原 FromSqlRaw 调用逻辑完全不用修改,无数据时会自动返回空列表,不会抛出异常。
方案2:自定义ADO.NET调用(适配无法修改存储过程的场景)
如果不允许修改存储过程逻辑,可以绕开 FromSqlRaw,直接通过底层ADO.NET执行存储过程并手动映射结果:
public async Task<List<MyDataModel>> GetMyDataAsync(SqlParameter param1, SqlParameter param2) { var result = new List<MyDataModel>(); await using var connection = dbContext.Database.GetDbConnection(); await using var command = connection.CreateCommand(); command.CommandText = "myProcedure"; command.CommandType = System.Data.CommandType.StoredProcedure; command.Parameters.AddRange(new[] { param1, param2 }); await connection.OpenAsync(); await using var reader = await command.ExecuteReaderAsync(); // 仅当存在有效结果集时做映射 if (reader.HasRows) { var completedPercentageIndex = reader.GetOrdinal(nameof(MyDataModel.CompletedPercentage)); var titleIndex = reader.GetOrdinal(nameof(MyDataModel.Title)); var codeIndex = reader.GetOrdinal(nameof(MyDataModel.Code)); while (await reader.ReadAsync()) { result.Add(new MyDataModel { CompletedPercentage = reader.GetInt32(completedPercentageIndex), Title = reader.IsDBNull(titleIndex) ? null : reader.GetString(titleIndex), Code = reader.IsDBNull(codeIndex) ? null : reader.GetString(codeIndex) }); } } return result; }
该方式不依赖EF的结果集结构校验逻辑,存储过程无返回时也会正常返回空列表。
内容的提问来源于stack exchange,提问作者Housesit Search
相关产品推荐
相关产品推荐

