51

我正在使用 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 数据库:

数据库架构

到现在为止还挺好!但是,我将插入到BodyandBodyHtml属性中的数据通常大于NVarChar列类型的最大允许长度,因此我希望 EF 为这些属性生成Text列。

但是,我似乎无法找到一种方法来做到这一点!经过相当多的谷歌搜索和阅读后,我尝试使用DataAnnotations这个答案中找到的信息指定列类型:

using System.ComponentModel.DataAnnotations;

...

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

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

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列仍然是NVarChar(4000),因此似乎忽略了注释。

任何人都可以帮忙吗?这似乎应该是一个相当普遍的要求,但我的搜索一直没有结果!

4

12 回答 12

77

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

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

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

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

于 2011-02-06T13:38:24.270 回答
32

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

[MaxLength]

或使用 EF 4.1 RC fluent API ...

protected override void OnModelCreating(ModelBuilder modelBuilder){
    modelBuilder.Entity<Article>()
        .Property(p => p.Body)
        .IsMaxLength();
}
于 2011-03-21T10:53:28.413 回答
9

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

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

有 ntext 但没有文本

于 2011-02-04T08:13:36.550 回答
6

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

[StringLength(4010)]

是否任何字符串>属性中定义的字符数都会触发验证异常,这与您在列上使用未定义字段大小的任何原因背道而驰,或者您在属性中使用大量数字并丢失属性提供的任何验证。如果您使用 StringLength 属性,最终您将使用验证机制来解决映射问题,而 Marcel Popescu 使用 Column 属性的答案是一个更好的解决方案,因为它使用映射属性来定义类型,并且仍然允许您使用用于验证的 StringLength 属性。

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

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

还应该注意的是,NText 是一种已弃用的数据类型(ntext、text 和 image (Transact-SQL) MS 联机丛书),建议使用 NVarChar(MAX) 代替

于 2011-02-23T18:32:26.537 回答
5

我知道,这可能为时已晚,但是:

采用:

[StringLength(-1)] 

这将创建一个 nText 字段。我设法使用 Compact Edition 4.0 数据库在该字段中存储了至少 25 KB。

于 2012-02-08T16:13:12.927 回答
5

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

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

或通过 Fluent API:

modelBuilder.Entity<YourEntityTypeHere>()
    .Property( e => e.Text)
    .HasColumnType("text");
于 2014-10-09T04:56:28.817 回答
1

你试过小写"text"吗?根据此 MSDN 讨论,数据提供者区分大小写。

于 2011-02-04T07:18:22.317 回答
1

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

[StringLength(1073741822)]

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

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

我正在使用它并且它可以工作,但我想知道这是否是一个好主意或者我是否遗漏了什么......有没有其他方法可以让代码首先知道我想要nvarchar(MAX)?

于 2011-02-16T15:38:00.933 回答
1

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

[StringLength(4010)]
于 2011-02-17T14:03:58.707 回答
1

同意这TypeName = "ntext"似乎可行,尽管我还必须添加:

[StringLength(Int32.MaxValue)]

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

于 2011-03-28T19:07:49.507 回答
1

如果您使用包管理器进行添加迁移和更新数据库,您可以通过添加storeType来修改创建表,如下所示:

       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);
于 2016-06-04T02:12:36.347 回答
1

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

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

你可以从你的onModelCreating()

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

你所有的strings 都会自动变成ntext列。

于 2017-05-19T22:30:48.157 回答