能否无需将自定义模型加入DbContext,映射EF Core存储过程结果至非实体模型?
无需DbSet,将EF Core存储过程结果映射到非实体模型
方案1:EF Core 7+ 原生SqlQuery方法
EF Core 7及以上版本提供了Database.SqlQuery<T>方法,直接支持查询非实体类型,无需在DbContext中注册DbSet<T>。
修改你的Controller代码如下:
// 调用存储过程并获取结果(参数化查询避免SQL注入) var spResults = await _context.Database.SqlQueryRaw<ModelSpDto>( "EXECUTE dbo.storedProcedure @UserId", new SqlParameter("@UserId", request.UserId) ).ToListAsync(); // 排序 var sortedResults = spResults.OrderByDescending(x => x.DateCreated).ToList(); // 分页 IPagedList<ModelSpDto> pagingData = await sortedResults.ToPagedListAsync( pageNumber: request.PageNumber, pageSize: request.PageSize ); // 映射响应 response.PagingData = pagingData.ToMappedPagedList<ModelSpDto, ModelSp2Dto>(_mapper);
方案2:旧版EF Core(低于7)用ADO.NET+映射
如果你的EF Core版本低于7,可以直接用ADO.NET执行存储过程,再将结果映射到ModelSpDto:
手动映射写法
var spResults = new List<ModelSpDto>(); var connection = _context.Database.GetDbConnection(); try { await connection.OpenAsync(); using (var command = connection.CreateCommand()) { command.CommandText = "dbo.storedProcedure"; command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@UserId", request.UserId)); using (var reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { spResults.Add(new ModelSpDto { DateCreated = reader.GetDateTime(reader.GetOrdinal("DateCreated")), // 按存储过程返回的列名,依次映射其他属性 }); } } } } finally { await connection.CloseAsync(); } // 后续排序、分页、映射逻辑和方案1一致 var sortedResults = spResults.OrderByDescending(x => x.DateCreated).ToList(); IPagedList<ModelSpDto> pagingData = await sortedResults.ToPagedListAsync( pageNumber: request.PageNumber, pageSize: request.PageSize ); response.PagingData = pagingData.ToMappedPagedList<ModelSpDto, ModelSp2Dto>(_mapper);
用Dapper简化映射
如果觉得手动映射繁琐,可以引入Dapper简化操作(需先通过NuGet安装Dapper包):
var connection = _context.Database.GetDbConnection(); await connection.OpenAsync(); var spResults = await connection.QueryAsync<ModelSpDto>( "dbo.storedProcedure", new { UserId = request.UserId }, commandType: CommandType.StoredProcedure ); await connection.CloseAsync(); // 后续排序、分页、映射逻辑同上
关键注意事项
- 必须使用参数化查询,禁止直接拼接参数,防止SQL注入风险
ModelSpDto的属性名称、类型要和存储过程返回的列名、类型严格匹配,否则会映射失败
内容的提问来源于stack exchange,提问作者Muhammad Bilal
相关产品推荐
相关产品推荐

