Entity Framework Core:忽略属性列并通过原生SQL赋值的方法
问题描述
定义如下Person实体类:
class Person { public string Name { get; set; } public string SomeData { get; set; } }
为避免SomeData在数据库生成对应列,在上下文配置中使用Ignore:
modelBuilder.Entity<Person>() .Ignore(a => a.SomeData); // 不在数据库创建该列
但执行原生SQL查询时:
var results = _dbContext.Persons .FromSqlRaw("SELECT Name, 'calculated by query' SomeData from Persons") .ToList();
发现SomeData属性最终为NULL。
核心需求:
- 不在数据库创建
SomeData列 - 允许通过原生SQL查询为该属性赋值
- 禁止使用DTO类或匿名类型
曾尝试先通过Ignore创建数据库,再改为HasComputedColumnSql的方案,虽能生效但不可行,询问能否为EF Core添加类似HasComputedRawSqlProperty的功能,实现不生成数据库列但支持原生SQL赋值。
可行解决方案
EF Core目前没有直接提供HasComputedRawSqlProperty这类专属API,但可以通过两种可靠方式实现需求:
方式一:[NotMapped]特性配合SqlQuery(EF Core 7.0+)
- 给
SomeData添加[NotMapped]特性,明确标记该属性不映射到数据库列:
using System.ComponentModel.DataAnnotations.Schema; class Person { public string Name { get; set; } [NotMapped] public string SomeData { get; set; } }
- 使用EF Core 7.0新增的
SqlQuery方法,直接绑定查询结果到实体属性:
var results = _dbContext.SqlQuery<Person>( "SELECT Name, 'calculated by query' AS SomeData FROM Persons" ).ToList();
若使用低于7.0的版本,可手动通过DbDataReader读取并赋值:
using var reader = _dbContext.Database.ExecuteReader("SELECT Name, 'calculated by query' AS SomeData FROM Persons"); var results = new List<Person>(); while (reader.Read()) { results.Add(new Person { Name = reader.GetString(0), SomeData = reader.GetString(1) }); }
方式二:配置为「仅查询绑定、不持久化」属性
不使用Ignore,而是通过上下文配置标记属性仅用于查询绑定,保存时忽略:
modelBuilder.Entity<Person>() .Property(p => p.SomeData) .HasColumnType("nvarchar(max)") // 匹配查询返回值类型 .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore); // 保存操作时忽略该属性
此配置下,EF Core不会在数据库创建SomeData列,但执行原生SQL查询时会自动将结果中的SomeData值绑定到实体属性。
关于新增API的说明
EF Core官方当前路线图中暂无添加HasComputedRawSqlProperty这类API的计划,但你可通过EF Core的GitHub仓库提交Feature Request,详细描述你的使用场景,官方会根据需求优先级评估是否纳入规划。
内容的提问来源于stack exchange,提问作者Artur
相关产品推荐
相关产品推荐

