如何让EF数据库优先模式自动生成无公共set的计算属性?
解决Entity Framework中计算列自动生成private set的问题
你的痛点我太懂了:EDMX生成的实体类里,标记为StoreGeneratedPattern="Computed"的计算列默认是公共的get; set;,导致代码里能错误赋值,保存时却静默失效,手动改成private set后,重新生成EDMX又会丢失修改。下面给你几个靠谱的自动解决办法:
方法1:自定义T4模板(最彻底的方案)
EF的EDMX默认用内置模板生成实体类,你可以替换成自定义T4模板,修改属性生成逻辑,让计算列自动生成private set:
- 在EDMX文件上右键,选择Add Code Generation Item,根据你的EF版本选对应的生成器(比如EF 6.x DbContext Generator),添加
.tt和.Context.tt两个模板文件。 - 打开实体类对应的T4模板(比如
YourModel.tt),找到生成属性的代码段,大概是这样:public <#=code.Escape(primitiveProperty)#> <#=code.Escape(property)#> { get { return _<#=code.Escape(property)#>; } set { SetProperty(ref _<#=code.Escape(property)#>, value); } } - 修改这段逻辑,判断属性的
StoreGeneratedPattern是否为Computed,如果是就把set设为private:public <#=code.Escape(primitiveProperty)#> <#=code.Escape(property)#> { get { return _<#=code.Escape(property)#>; } <# if (property.StoreGeneratedPattern == StoreGeneratedPattern.Computed) { #> private set { SetProperty(ref _<#=code.Escape(property)#>, value); } <# } else { #> set { SetProperty(ref _<#=code.Escape(property)#>, value); } <# } #> } - 保存模板后重新生成实体类,以后每次更新EDMX,计算列的set都会自动是private,不会再丢失修改。
方法2:分部类扩展(临时过渡方案)
如果你暂时不想改T4模板,可以用分部类重新定义计算列属性,覆盖默认的公共set:
创建一个独立的分部类文件(不要放在EDMX自动生成的文件里):
public partial class Test { // 重新定义计算列,设置private set public decimal Field2 { get; private set; } }
不过这个方法有个小缺点:如果EDMX里计算列的类型或名称变化,你需要手动同步这个分部类的代码,不如T4模板省心。
方法3:升级到EF Core(长期推荐)
如果有机会升级到EF Core,它对计算列的处理更智能:数据库里的计算列会被自动识别,生成的实体类中标记为[DatabaseGenerated(DatabaseGeneratedOption.Computed)]的属性,默认只有getter(或private set,取决于EF Core版本),从根源上避免了错误赋值的问题,而且代码生成工具(比如Scaffold-DbContext)会自动维护这个设置。
补充说明
早期EF默认生成公共set,是考虑到某些离线场景可能需要临时设置计算列值,但显然这个设计在你的场景里带来了隐患。自定义T4模板是最彻底的解决方案,既能保留自动生成的便利性,又能从代码层面阻止错误赋值。
内容的提问来源于stack exchange,提问作者masa
相关产品推荐
相关产品推荐

