EF7调用存储过程返回自定义模型,避免生成对应数据库表
问题描述
我已使用EF7完成基础表的映射,且运行正常。现在需要调用存储过程,返回由多表数据组合而成的自定义模型ReportSummary的列表。
我在上下文类中映射该模型:
public class MyDbContext : DbContext { // ... public DbSet<ReportSummary> ReportSummary { get; set; } // ... }
调用存储过程的代码如下:
public async Task<IEnumerable<ReportSummary>> GetUserReportSummaries(Guid userId, bool showDeleted) { return await _context .ReportSummary .FromSql($"EXECUTE dbo.GetReportSummaries {userId}, {showDeleted}") .ToListAsync(); }
当前映射方式可正常获取预期结果,但问题在于:通过DbSet映射后,生成数据库更新SQL时会自动创建ReportSummary表,而我并不需要该表。
若不添加DbSet,存储过程调用则无法正常执行。想确认:
- 当前映射方式是否正确?
- 如何使用该自定义模型却不生成对应数据库表?
- Entity Framework能否使用非表模型?
- 是否存在无需修改迁移代码的正确方案,实现从存储过程返回复杂类型结果?
解决方案
当前映射方式的问题
你之前用DbSet<ReportSummary>的方式并不适合非表模型场景,因为EF会默认将DbSet对应的实体标记为需要持久化的数据库表,因此迁移时会自动生成建表语句。
正确方案1:使用无键实体(Keyless Entity)
EF7官方提供了无键实体映射,专门用于处理存储过程结果、视图、临时表这类不需要对应数据库表的模型:
- 移除上下文类中的
DbSet<ReportSummary>,在OnModelCreating方法中配置无键实体:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 其他实体配置... modelBuilder.Entity<ReportSummary>().HasNoKey(); }
- 调用存储过程时,通过
Set<ReportSummary>()获取实体集合:
public async Task<IEnumerable<ReportSummary>> GetUserReportSummaries(Guid userId, bool showDeleted) { return await _context .Set<ReportSummary>() .FromSql($"EXECUTE dbo.GetReportSummaries {userId}, {showDeleted}") .ToListAsync(); }
这种方式下,EF不会为ReportSummary生成任何建表迁移语句,完全适配非表模型的需求。
正确方案2:直接使用原生SQL查询映射
如果不想配置实体,也可以用EF7新增的SqlQuery<T>方法,直接将存储过程结果映射到自定义模型:
public async Task<IEnumerable<ReportSummary>> GetUserReportSummaries(Guid userId, bool showDeleted) { return await _context .Database .SqlQuery<ReportSummary>($"EXECUTE dbo.GetReportSummaries {userId}, {showDeleted}") .ToListAsync(); }
该方法不需要提前配置任何实体映射,只要模型属性和存储过程返回的列名一一匹配即可。
关键说明
- EF完全支持非表模型,无键实体就是官方为这类场景设计的标准解决方案。
- 上述两种方案都不需要修改迁移代码,迁移过程中不会生成
ReportSummary的建表语句。
内容的提问来源于stack exchange,提问作者Cubic8
相关产品推荐
相关产品推荐

