EF Core中如何为JSON列指定列的MaxLength?
问题描述
现有两个表示数据库表的类:
public class Parent { public Child Child { get; set; } } public class Child { public string PropertyA { get; set; } public string PropertyB { get; set; } }
对应的DbContext配置如下:
public class SomeContext : DbContext { // ...其他配置 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Parent>().OwnsOne(x => x.Child, y => y.ToJson()); base.OnModelCreating(modelBuilder); } }
执行迁移命令:
dotnet ef migrations add SomeContext_Initial
生成的迁移代码中,Child列默认被设置为nvarchar(max):
protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "Parent", columns: table => new { Child = table.Column<string>(type: "nvarchar(max)", nullable: false) } ); // ...其他代码 }
使用SQL Server时,即使序列化后的内容远小于8060字节,nvarchar(max)类型仍可能导致列被移至ROW_OVERFLOW_DATA分配单元,影响性能。尝试过给Child属性加[MaxLength(1000)]特性,或在配置中使用.HasAnnotation("MaxLength", 1000)、指定列类型为nvarchar(1000),均未生效,希望找到无需手动编辑迁移文件的解决方案。
解决方案
当使用ToJson()将Owned Entity序列化为单个字符串列时,需要直接针对这个序列化后的列配置长度,而非Owned Entity内部的属性。修改OnModelCreating中的配置如下:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Parent>() .OwnsOne(x => x.Child, y => { y.ToJson(); // 方式1:直接指定列类型为nvarchar(1000) y.Property(x => x).HasColumnType("nvarchar(1000)"); // 方式2:通过HasMaxLength设置长度,EF Core会自动映射为对应nvarchar类型 // y.Property(x => x).HasMaxLength(1000); }); base.OnModelCreating(modelBuilder); }
说明
y.Property(x => x)指向的是被序列化的整个Child对象对应的数据库列,而非Child类的某个属性。- 两种方式都能让EF Core生成
nvarchar(1000)类型的列,而非默认的nvarchar(max)。 - 重新执行迁移命令后,生成的迁移代码中
Child列的类型会变为nvarchar(1000),无需手动修改迁移文件。
内容的提问来源于stack exchange,提问作者Hominis_06
相关产品推荐
相关产品推荐

