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

Mar*_*ell 49 c# entity-framework sql-server-ce data-annotations ef-code-first

我正在使用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; }
}
Run Code Online (Sandbox Code Playgroud)

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

DB Schema

到现在为止还挺好!然而,数据I将被插入到BodyBodyHtml属性是常规比对于最大允许长度更大NVarChar的列类型,所以想要EF生成Text这些属性列.

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

using System.ComponentModel.DataAnnotations;

...

[Column(TypeName = "Text")]
public string Body { get; set; }
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

但我不知道我应该指定什么命名空间或别名,我找不到任何可以告诉我的东西.

我也尝试按照此参考更改注释:

using System.Data.Linq.Mapping;

...

[Column(DbType = "Text")]
public string Body { get; set; }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,创建一个数据库,但该Body列仍然是一个NVarChar(4000),因此似乎忽略了注释.

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

Mar*_*scu 70

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

[Column(TypeName = "ntext")]
public string Body { get; set; }
Run Code Online (Sandbox Code Playgroud)

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

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

  • 当你的try插入超过4,000个字符时,模型验证仍然会引起麻烦并引发错误,即使数据库设置为ntext,但是当它读取"string"类型时,它会自动猜测max length = 4000,忽略数据库中的类型.对我来说仍然没有解决. (3认同)

小智 30

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

[MaxLength]
Run Code Online (Sandbox Code Playgroud)

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

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

  • 对于仍在 SQL Server CE + EF 代码优先下遇到此问题的任何人,如果您尝试 typeName=ntext 但仍然收到错误“该字段必须是具有最大长度的字符串或数组类型”,那么这就是您正在寻找的解决方案'4000'”,数据长度 &gt;4000...[MaxLength] 是您在列上所需的全部内容,使其成为 ntext 并允许使用完整数据长度 (2认同)

Kri*_*aes 9

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

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

有ntext但没有文字


nak*_*hak 6

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

[StringLength(4010)]
Run Code Online (Sandbox Code Playgroud)

是否任何字符串>属性中定义的字符数将触发验证异常,这种情况与您在列上使用未定义字段大小的任何原因相反,或者您在属性中使用了大量数字并丢失属性提供的任何验证.最终,如果使用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)");
}
Run Code Online (Sandbox Code Playgroud)

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

  • 没错,只检查了Sql CE 4.0 Docs(http://msdn.microsoft.com/en-us/library/ms172424%28v=SQL.110%29.aspx)但ntext类型无法与任何(sql server)一起使用)字符串函数,它将数据存储在一个单独的数据页中到表的其余部分,所以个人除非我有一个非常明确的理由不坚持使用nvarchar(max)的性能和功能原因 (2认同)

小智 5

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

使用:

[StringLength(-1)] 
Run Code Online (Sandbox Code Playgroud)

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


Moe*_*oes 5

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

[Column(TypeName="text")]
public string Text { get; set; }
Run Code Online (Sandbox Code Playgroud)

或通过 Fluent API:

modelBuilder.Entity<YourEntityTypeHere>()
    .Property( e => e.Text)
    .HasColumnType("text");
Run Code Online (Sandbox Code Playgroud)