EF Code First 迁移 maxLength 设置为 4000 而不是 max

lc.*_*lc. -1 entity-framework ef-code-first entity-framework-migrations

tl;dr:我有一个应该是的列,NVARCHAR(MAX)但是用脚手架进行迁移Add-Migration给了我一个最大长度为 4000 in 的列Up()。我必须做什么才能做到这一点MAX


考虑以下模型:

public class Foo
{
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    [Required]
    [DataType(DataType.MultilineText)]
    public string Memo { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我在以下地方建立了两个约定Context.OnModelCreating

  • 将任何未配置的字符串属性的默认 maxLength 设置为 1024 的约定,其中包含以下行:

    Properties<string>().Configure(c => c.HasMaxLength(1024));
    
    Run Code Online (Sandbox Code Playgroud)
  • 基于属性的约定,读取DataTypeAttribute并相应地设置一些属性,即列类型和长度:

        switch (attribute.DataType)
        {
            case DataType.MultilineText:
                configuration.HasColumnType("nvarchar").IsMaxLength();
                break;
            case DataType.EmailAddress:
                configuration.HasColumnType("nvarchar").HasMaxLength(255);
                break;
        }
    
    Run Code Online (Sandbox Code Playgroud)

我在设置迁移之前测试了这一切,它工作得很好,给了我下表 - 请注意,备忘录被创建为NVARCHAR(MAX)

CREATE TABLE dbo.Foo (
    Id INT IDENTITY NOT NULL,
    Name NVARCHAR(100) NOT NULL,
    Memo NVARCHAR(MAX) NOT NULL,
    Email NVARCHAR(255) NOT NULL,
    CONSTRAINT [PK_Foo] PRIMARY KEY (Id)
)
Run Code Online (Sandbox Code Playgroud)

然后我启用了迁移并添加了一个,并在 中获得了下表定义Up()

CreateTable(
    "dbo.Foo",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            Name = c.String(nullable: false, maxLength: 100),
            Memo = c.String(nullable: false, maxLength: 4000),
            Email = c.String(nullable: false, maxLength: 255),
        })
    .PrimaryKey(t => t.Id)
Run Code Online (Sandbox Code Playgroud)

世界卫生大会?那是从哪里来maxLength: 4000的?这不是MAX我所期望的,甚至也不是1024我在第一次约定中配置为默认值的。它当然尊重100and 255of Nameand Email(证明我的基于属性的约定是有效的)......

那么,这是框架中的错误,还是我不理解迁移的某些内容?无论哪种方式,我该怎么做才能让 Code First Migrations 尊重我的IsMaxLength()

lc.*_*lc. 5

显然在上下文中与在迁移中IsMaxLength() 具有不同的含义。在上下文中,它创建一列,NVARCHAR(MAX)但一旦启用迁移,这将被解释为“该列允许的最大可能值,除了 MAX”。正如 @marc_s 在评论中指出的那样,一列的大小为 4000 nvarchar

事实上,虽然我在迁移之外阅读了这篇文章,但设置HasMaxLength(int.MaxValue)和调用Add-Migration给了我以下错误:

(0,0):错误 0026:MaxLength“2147483647”无效。对于“nvarchar”类型,长度必须介于“1”和“4000”之间。

多玩了一会儿,我决定尝试一下HasColumnType("nvarchar(MAX)"),令我惊讶的是,它成功了!因此,替换上面约定中的调用是可行的。

我找不到任何方法来读出IsMaxLength()可以设置类型的任何地方的结果(例如IStoreModelConvention为时已晚),所以这不是最漂亮的解决方案,但至少我可以继续前进。