如何阻止Entity Framework将属性设为可空?EF6.1项目求助
解决EF6.1数据库优先下视图计算属性被强制设为可空的问题
我太懂这种手动改完属性,一更新EDMX就打回原形的崩溃感了!结合你用的EF6.1、数据库优先+T4代码生成的场景,给你几个能彻底解决的方案,按持久度排序:
方案1:自定义T4实体生成模板(一劳永逸)
这是最靠谱的方案,因为每次代码生成都走T4模板,改一次就不用再手动改实体了。步骤如下:
- 在你的项目里找到生成实体的T4文件(一般叫
YourModelName.tt,和EDMX文件同级),右键选择“打开方式”→“XML编辑器”打开它。 - 找到生成属性的代码块,通常是类似这样的循环:
foreach (var edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && !p.IsNavigationProperty)) { #> <#=codeStringGenerator.Property(edmProperty)#> <# } - 我们需要重写属性的可空性判断逻辑。先判断当前实体是不是视图(可以通过实体的命名规则,比如名字带
View,或者更准确的:检查实体在SSDL里的定义是否来自视图,简单点可以用命名过滤),然后对这类实体的属性强制设为非可空:
替换成类似这样的代码:
这里直接跳过了默认的foreach (var edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && !p.IsNavigationProperty)) { // 判断是否为视图实体,这里根据你的视图命名规则调整 var isViewEntity = entity.Name.EndsWith("View"); // 强制视图的计算属性为非可空 var isNullable = isViewEntity ? false : edmProperty.Nullable; #> [Required] public <#=code.Escape(edmProperty.TypeUsage.EdmType)#><#=isNullable ? "?" : ""#> <#=code.Escape(edmProperty)#> { get; set; } <# }codeStringGenerator.Property方法,自己生成属性代码,同时给视图属性加上[Required]特性(可选,如果你需要数据验证的话)。 - 保存模板后右键选择“运行自定义工具”,生成的实体里视图的计算属性就会变成非可空类型了,后续更新EDMX也不会被覆盖。
方案2:修改EDMX的存储模型(SSDL)
如果不想动T4模板,可以直接修改EDMX的底层XML,让EF识别属性为非空:
- 右键EDMX文件→“打开方式”→“XML编辑器”。
- 找到
<edmx:StorageModels>节点下对应的视图实体(比如<EntityType Name="YourViewName">)。 - 找到对应的计算属性,把
Nullable="true"改成Nullable="false",比如:<Property Name="CalculatedValue" Type="int" Nullable="false" /> - 保存EDMX后重新生成代码,属性就变成非可空了。
⚠️ 注意:下次从数据库更新模型时,这个修改可能会被覆盖,所以如果经常更新EDMX,还是推荐方案1。
方案3:调整数据库视图的定义
EF是从SQL Server返回的列元数据判断可空性的,有时候即使计算值有默认值,SQL Server还是会标记列为可空。你可以修改视图,让SQL Server认为该列非空:
比如原本的计算列是:
SELECT Column1, Column2, (Column1 + Column2) AS CalculatedValue FROM YourTable
改成:
SELECT Column1, Column2, ISNULL((Column1 + Column2), 0) AS CalculatedValue FROM YourTable
或者对于字符串类型用ISNULL(计算表达式, ''),这样SQL Server会返回该列的可空性为NOT NULL,下次更新EDMX时,EF就会生成非可空属性了。
内容的提问来源于stack exchange,提问作者rjzii
相关产品推荐
相关产品推荐

