在现有 SQL Server 数据库上使用实体框架时禁用 VARCHAR 和 NVARCHAR 之间的转换

Posted

技术标签:

【中文标题】在现有 SQL Server 数据库上使用实体框架时禁用 VARCHAR 和 NVARCHAR 之间的转换【英文标题】:Disable conversion between VARCHAR and NVARCHAR when using Entity Framework over an existing SQL server database 【发布时间】:2018-08-25 18:40:59 【问题描述】:

我有一个现有的数据库 SQL 服务器,我正在使用 EF6。假设我有以下代码:

private sealed class Foo

    public int Id  get; set; 

    public string Bar  get; set; 


private sealed class FooConfiguration : EntityTypeConfiguration<Foo>

    public FooConfiguration()
    
        ToTable("Foos");
        HasKey(e => e.Id);
        Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    


private class FooContext : DbContext

    public FooContext(string connectionString)
        : base(connectionString)
    
        Database.SetInitializer<FooContext>(null);
    

    public virtual DbSet<Foo> Foos  get; set; 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new FooConfiguration());
    

用法:

const string bar = "حالياً البحث عبر جوجل";
int fooId;
using (var db = new FooContext(connectionString))

    var foo = db.Foos.Add(new Foo  Bar = bar );
    db.SaveChanges();
    fooId = foo.Id;


using (var db = new FooContext(connectionString))

    var foo = db.Foos.First(f => f.Id == fooId);
    if (foo.Bar != bar)
    
        Console.WriteLine("Oops!");
    

什么可能出错?好吧,如果Bar 列的类型是VARCHAR(MAX) 而不是NVARCHAR(MAX),那么我们就处于不利的位置,因为VARCHAR 无法正确存储该Unicode 字符串,所以我们得到了一堆问号。

所以,问题是:我可以如何禁用VARCHARNVARCHAR 之间的这种转换并强制EF 在SaveChanges 期间抛出某种类型不匹配异常吗?我尝试在我的配置类中使用它:

Property(e => e.Bar).IsUnicode(true);
Property(e => e.Bar).HasColumnType("NVARCHAR(MAX)");

但它什么也没做。

提前致谢。

【问题讨论】:

这听起来更像是一个 xy 问题。如果您需要确保存储 unicode 字符,那么您需要确保正确声明数据类型。如果您因为使用了错误的数据类型而丢失了数据,那不是应用程序或数据引擎的错;就是需要正确配置数据类型。 @Larnu 你说得对,这是我的数据库中类型不正确的问题,而不是应用程序代码。在我们在“Foos”表中插入无数行之前,我只是在寻找一种可以帮助我找到这些问题的解决方案 这是代码优先吗? this question 中有一些指针(和一个库),它基本上以更一般的方式询问您要问的内容,但对于 Code First,您可能会受到影响,因为 EF 不会费力地检索元数据并首先比较注释.请注意,这实际上是一个非常困难的问题。如果无法假设您的数据库与您的模型匹配(当然,一些架构差异是良性的,但这取决于应用程序),那么大多数数据访问都是无效或低效的。 【参考方案1】:

string 列的默认数据类型为nvarchar(MAX),您无需在列中设置数据类型即可更改为NVARCHAR(MAX)。 Ef 具有指定它的默认约定。 here 解释为了解约定。

如果你想为你的模型配置一般约定,你可以这样做:

public class DataTypeConvention : Convention

    public DataTypeConvention()
    
        Properties<string>().Configure(config =>  config.HasColumnType("nvarchar(MAX)"); );
    

在您的 DbContext 上:

protected override void OnModelCreating(DbModelBuilder modelBuilder)

   modelBuilder.Conventions.Add(new DataTypeConvention());

【讨论】:

以上是关于在现有 SQL Server 数据库上使用实体框架时禁用 VARCHAR 和 NVARCHAR 之间的转换的主要内容,如果未能解决你的问题,请参考以下文章

如何更改实体框架项目以使用 Microsoft SQL Server

同时将实体框架与 SQL Server 和 SQLite 数据库一起使用

使用 SQL Server 数据库和实体框架错误的 Windows 应用程序部署

如何将 sql server express 数据库附加到实体框架中的项目

在EF6中切换MySQL / SQL Server

实体框架和 SQL Server 视图