Entity Framework 6.4.4 Database First生成SQL误用varchar替代nvarchar求助
解决Entity Framework 6.4.4 Database First下nvarchar(max)被识别为varchar(max)的问题
从你的描述来看,核心矛盾是:数据库、EDMX的概念模型和存储模型都已配置为nvarchar(max),但EF运行时仍将Template属性识别为**非Unicode(AnsiString)**类型,最终导致非Unicode字符存储乱码。下面是具体的排查和解决步骤:
1. 用Fluent API强制覆盖模型配置
你的DbContext当前因Database First模式抛出UnintentionalCodeFirstException,但我们可以修改OnModelCreating方法,通过Fluent API直接指定属性类型——这种方式优先级最高,能绕过EDMX可能存在的映射问题:
Partial Public Class MyDbContext Inherits DbContext Public Sub New() MyBase.New("name=MyDbContext") End Sub Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder) ' 移除原异常抛出,添加Fluent配置 modelBuilder.Entity(Of LetterTemplates)() .Property(Function(t) t.Template) .IsUnicode(True) ' 强制启用Unicode支持 .HasColumnType("nvarchar(max)") ' 指定数据库列类型 MyBase.OnModelCreating(modelBuilder) End Sub Public Overridable Property LetterTemplates() As DbSet(Of LetterTemplates) ... End Sub
2. 检查EDMX映射层是否同步
有时候概念模型和存储模型的设置是正确的,但**映射层(MSL)**没有正确关联两者,导致EF读取错误的元数据:
- 右键EDMX文件,选择「Open With」→「XML (Text) Editor」
- 搜索
<EntityContainerMapping>节点下的<EntitySetMapping Name="LetterTemplates"> - 找到对应
<ScalarProperty Name="Template" ColumnName="Template" />的配置,确认存储模型(SSDL)中对应的列确实是Type="nvarchar(max)",且映射关系没有错位。
如果发现映射错误,可以手动修正XML,或者重新从数据库更新模型。
3. 清除EF元数据缓存
EF会缓存模型元数据,即使修改了EDMX,旧缓存可能仍然生效:
- 清理项目的
bin和obj目录,重新编译 - 重启应用程序池或控制台应用
- 若为Web项目,可以在连接字符串中明确指定元数据路径,确保加载最新EDMX:
<connectionStrings> <add name="MyDbContext" connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;data source=...;initial catalog=...;integrated security=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
4. 修改T4模板生成正确的DataAnnotations
如果实体类通过T4模板自动生成,可能模板没有正确读取EDMX中的Unicode=True设置,导致生成的实体缺少标注:
- 打开EDMX对应的T4模板(通常是
Model.tt) - 找到生成String属性的代码块,添加
[Unicode(true)]或[Column(TypeName = "nvarchar(max)")]标注:
重新生成实体类后,EF会根据这些标注识别属性的Unicode类型。<# For Each property in entity.Properties If property.TypeUsage.EdmType.Name = "String" Then #> <#If ((property.TypeUsage.Facets["Unicode"] IsNot Nothing) AndAlso CBool(property.TypeUsage.Facets["Unicode"].Value)) Then#> <System.ComponentModel.DataAnnotations.Schema.Unicode(True)> <System.ComponentModel.DataAnnotations.Schema.Column(TypeName:="nvarchar(max)")> <#End If#> Public Property <#=property.Name#> As String <# End If Next #>
5. 彻底重新同步EDMX与数据库
如果上述方法都无效,尝试完全重置模型同步:
- 在EDMX设计器中删除
LetterTemplates实体 - 右键设计器空白处,选择「Update Model from Database」
- 选中
LetterTemplates表,确保同步最新的列类型和排序规则 - 保存EDMX并重新编译
问题根源分析
你看到的Type = AnsiString是EF运行时元数据的标识,说明EF没有正确读取到EDMX中Unicode=True的设置,可能原因包括:
- EDMX映射层(MSL)配置错误,导致概念模型的Unicode设置未映射到存储模型
- EF元数据缓存未更新,仍使用旧的模型配置
- T4模板生成实体类时,未正确应用EDMX中的Unicode配置
内容的提问来源于stack exchange,提问作者kolin
相关产品推荐
相关产品推荐

