tl; dr:我的列应该是NVARCHAR(MAX)
但是使用Add-Migration
进行迁移的脚手架会在Up()
中为我提供一个最大长度为4000的列。我需要做些什么才能将其变为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; }
}
我在Context.OnModelCreating
中设置了两个约定:
一种约定,它将任何未配置为1024的字符串属性的默认maxLength设置为1024,其中包含以下行:
Properties<string>().Configure(c => c.HasMaxLength(1024));
基于属性的约定,它读取DataTypeAttribute
并相应地设置一些属性,即列类型和长度:
switch (attribute.DataType)
{
case DataType.MultilineText:
configuration.HasColumnType("nvarchar").IsMaxLength();
break;
case DataType.EmailAddress:
configuration.HasColumnType("nvarchar").HasMaxLength(255);
break;
}
我在设置迁移之前测试了这一切,并且它工作得很漂亮,给了我下面的表格 - 请注意,Memo正在创建为 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)
)
然后我启用了迁移并添加了一个,并在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)
什? maxLength: 4000
来自哪里?这不是我期望的MAX
,也不是我在第一次约定时将1024
配置为默认值。它肯定尊重100
和255
Name
和Email
(证明我的基于属性的约定有效)......
那么,这是一个框架中的错误,还是有一些我不理解的迁移?无论哪种方式,我可以做些什么来使Code First Migrations尊重我的IsMaxLength()
?
答案 0 :(得分:4)
显然,IsMaxLength()
在上下文与迁移中具有不同的含义。在上下文中,它会创建一个NVARCHAR(MAX)
列,但是一旦启用迁移,这将被解释为“列允许的最大可能值,MAX除外”。正如@marc_s在评论中指出的那样,nvarchar
列为4000。
事实上,虽然我在移植之外阅读此内容,但设置HasMaxLength(int.MaxValue)
并调用Add-Migration
会给我以下错误:
(0,0):错误0026:MaxLength'2147483647'无效。 'nvarchar'类型的长度必须介于'1'和'4000'之间。
多玩一点,我决定尝试HasColumnType("nvarchar(MAX)")
,这让我惊讶工作!因此,替换上述约定中的调用有效。
我找不到任何方法可以在任何可以设置类型的地方读出IsMaxLength()
的结果(例如IStoreModelConvention
为时已晚),所以这不是最漂亮的解决方案,而是在至少我可以前进。