如何指定属性应生成TEXT列而不是nvarchar(4000)

时间:2011-02-04 07:13:39

标签: c# entity-framework ef-code-first sql-server-ce data-annotations

我正在使用Entity Framework的Code First功能,我正在试图弄清楚如何指定在自动生成数据库时应该创建的列数据类型。

我有一个简单的模型:

public class Article
{
    public int ArticleID { get; set; }

    public string Title { get; set; }
    public string Author { get; set; }
    public string Summary { get; set; }
    public string SummaryHtml { get; set; }
    public string Body { get; set; }
    public string BodyHtml { get; set; }
    public string Slug { get; set; }

    public DateTime Published { get; set; }
    public DateTime Updated { get; set; }

    public virtual ICollection<Comment> Comments { get; set; }
}

当我运行我的应用程序时,将使用以下模式自动创建SQL CE 4.0数据库:

DB Schema

到目前为止,真好!但是,我将插入BodyBodyHtml属性的数据通常大于NVarChar列类型的最大允许长度,因此我希望EF生成{{1}这些属性的列。

然而,我似乎找不到办法做到这一点!经过大量谷歌搜索和阅读后,我尝试使用Text中的this answer中的信息指定列类型:

DataAnnotations

这会引发以下异常(删除数据库并重新运行应用程序时):

using System.ComponentModel.DataAnnotations;

...

[Column(TypeName = "Text")]
public string Body { get; set; }

但我不知道我应该指定哪个命名空间或别名,我找不到任何可以告诉我的内容。

我还尝试按照this reference更改注释:

Schema specified is not valid. Errors: (12,6) : error 0040: The Type text is not qualified with a namespace or alias. Only PrimitiveTypes can be used without qualification.

在这种情况下,数据库创建,但using System.Data.Linq.Mapping; ... [Column(DbType = "Text")] public string Body { get; set; } 列仍为Body,因此似乎忽略了注释。

有人可以帮忙吗?这似乎应该是一个相当普遍的要求,但我的搜索却毫无结果!

12 个答案:

答案 0 :(得分:69)

我很欣赏现有答案所付出的努力,但我还没有发现它实际上回答了这个问题......所以我对此进行了测试,并发现了

[Column(TypeName = "ntext")]
public string Body { get; set; }

(来自System.ComponentModel.DataAnnotations的那个)将用于创建ntext类型列。

(我对接受的答案的问题是它似乎表明你应该更改界面中的列类型,但问题是如何以编程方式进行。)

答案 1 :(得分:30)

您可以使用以下DataAnnotation,Code-First将生成数据库允许的最大大小的数据类型。在Sql CE的情况下,它会产生一个底层的ntext列。

[MaxLength]

或使用EF 4.1 RC流畅的API ......

protected override void OnModelCreating(ModelBuilder modelBuilder){
    modelBuilder.Entity<Article>()
        .Property(p => p.Body)
        .IsMaxLength();
}

答案 2 :(得分:9)

你试过ntext吗?我刚刚创建了一个SQL CE 4.0数据库,当我手动向表中添加一列时,我注意到text在数据类型列表中不可用ntext。就像您可以选择nvarchar但不是varchar

不幸的是,您可以选择的最大nvarchar尺寸是4000.所以nvarchar(max)也不是一个选项。

There is ntext but no text

答案 3 :(得分:6)

使用字符串长度属性的问题,例如

[StringLength(4010)]

是否有任何字符串&gt;属性中定义的字符数将触发验证异常,这种情况与您在列上使用未定义的字段大小的任何原因相反,或者您在属性中使用了大量数字并且丢失了由该属性提供的任何验证属性。最终,如果使用StringLength属性,则使用验证机制来解决映射问题,其中使用Column属性的Marcel Popescu的答案是一个更好的解决方案,因为它使用映射属性来定义类型,并且仍然允许您使用验证的StringLength属性。

另一种选择是使用EF4 CTP5流畅API并在DbContext中的OnModelCreating事件中定义列映射,例如

protected override void OnModelCreating(ModelBuilder modelBuilder){
    modelBuilder.Entity<Article>()
    .Property(p => p.Body)
    .HasColumnType("nvarchar(max)");
}

另外需要注意的是NText是一种不推荐使用的数据类型(ntext, text, and image (Transact-SQL) MS Books Online),建议在其位置使用NVarChar(MAX)

答案 4 :(得分:5)

我知道,这可能是一年太晚但是:

使用:

[StringLength(-1)] 

这将创建一个nText字段。我设法在该领域存储至少25K字节 Compact Edition 4.0数据库。

答案 5 :(得分:4)

您可以使用System.ComponentModel.DataAnnotations.Schema.ColumnAttribute

[Column(TypeName="text")]
public string Text { get; set; }

或通过Fluent API:

modelBuilder.Entity<YourEntityTypeHere>()
    .Property( e => e.Text)
    .HasColumnType("text");

答案 6 :(得分:1)

您是否尝试过小写"text"?根据{{​​3}},数据提供者区分大小写。

答案 7 :(得分:1)

此DataAnnotation将使Code-First在sql

中生成nvarchar(MAX)列
[StringLength(1073741822)]

不确定其他大数字是否也一样......我使用计算器和nvarchar(MAX)规格得到了这个。

我是否尝试使用SQL Server 2005 Express,但没有使用CE

我正在使用它并且它有效,但我想知道它是否是一个好主意或者我是否遗漏了某些东西......是否还有其他方法可以让代码首先知道我想要nvarchar(MAX )?

答案 8 :(得分:1)

此DataAnnotation将使Code-First在sql中生成nvarchar(MAX)列:)

[StringLength(4010)]

答案 9 :(得分:1)

同意TypeName = "ntext"似乎有效,但我还要添加:

[StringLength(Int32.MaxValue)]

停止默认字符串长度128阻碍。

答案 10 :(得分:1)

如果您不想注释所有属性并使用现代EF,请使用约定:

public class StringNTextConvention : Convention {
  public StringNTextConvention() {
    Properties<string>().Configure(p => p.HasColumnType("ntext"));                    
  }
}

您可以从onModelCreating()

中拨打电话
modelBuilder.Conventions.Add(new StringNTextConvention());

并且您的所有string将自动转换为ntext列。

答案 11 :(得分:0)

如果您使用程序包管理器添加迁移和更新数据库,您可以通过添加 storeType 来修改create table,如下所示:

       CreateTable(
            "dbo.Table_Name",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Title = c.String(nullable: false, maxLength: 500),
                    Body = c.String(unicode: false, storeType: "ntext"),
                })
            .PrimaryKey(t => t.ID);