web-dev-qa-db-fra.com

Comment spécifier qu'une propriété doit générer une colonne TEXT plutôt qu'un nvarchar (4000)

Je travaille avec la fonctionnalité Code First d'Entity Framework et j'essaie de comprendre comment je peux spécifier les types de données de colonne à créer lors de la génération automatique de la base de données.

J'ai un modèle simple:

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; }
}

Lorsque j'exécute mon application, une base de données SQL CE 4.0 est automatiquement créée avec le schéma suivant:

DB Schema

Jusqu'ici tout va bien! Cependant, les données que je vais insérer dans les propriétés Body et BodyHtml sont régulièrement supérieures à la longueur maximale autorisée pour le type de colonne NVarChar. Je souhaite donc que EF génère des colonnes Text pour ces propriétés.

Cependant, je n'arrive pas à trouver un moyen de le faire! Après un peu de recherche sur Google et de lecture, j'ai essayé de spécifier le type de colonne en utilisant DataAnnotations, à partir des informations trouvées dans cette réponse :

using System.ComponentModel.DataAnnotations;

...

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

Cela lève l'exception suivante (lorsque la base de données est supprimée et que l'application est réexécutée):

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.

Mais je ne sais pas quel espace de noms ni quel alias je devrais spécifier, et je n'ai rien trouvé qui puisse me le dire.

J'ai aussi essayé de changer l'annotation selon cette référence :

using System.Data.Linq.Mapping;

...

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

Dans ce cas, une base de données est créée, mais la colonne Body est toujours une NVarChar(4000); il semble donc que l'annotation est ignorée.

Quelqu'un peut-il aider? Cela semble être une exigence assez courante, mais ma recherche a été infructueuse!

49
Mark Bell

J'apprécie l'effort consenti pour la réponse existante, mais je ne l'ai pas trouvée répondre à la question ... j'ai donc testé cela et découvert que

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

(celui de System.ComponentModel.DataAnnotations) fonctionnera pour créer une colonne de type ntext.

(Mon problème avec la réponse acceptée est qu'il semble indiquer que vous devez changer le type de colonne dans l'interface, mais la question est de savoir comment procéder par programme.)

69
Marcel Popescu

Vous pouvez utiliser le DataAnnotation suivant et Code-First générera le type de données de taille maximale autorisée par la base de données. Dans le cas de Sql CE, il en résulte une colonne ntext sous-jacente.

[MaxLength]

ou en utilisant l'API EF 4.1 RC fluent ...

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

Avez-vous essayé ntext? Je viens de créer une base de données SQL CE 4.0 et, lorsque j'ajoute manuellement une colonne à une table, je remarque que text n'est pas disponible dans la liste des types de données alors que ntext l'est. Tout comme vous pouvez choisir nvarchar mais pas varchar.

Malheureusement, la plus grande taille nvarchar que vous pouvez choisir est 4000. Donc, nvarchar(max) n'est pas non plus une option.

There is ntext but no text

9
Kristof Claes

Le problème lié à l’utilisation de l’attribut string length, par exemple.

[StringLength(4010)]

Est-ce que n'importe quelle chaîne> le nombre de caractères défini dans l'attribut va déclencher une exception de validation, ce qui va à l'encontre de toute raison pour laquelle vous utiliseriez une taille de champ non définie sur une colonne, ou vous utilisiez un nombre énorme dans l'attribut et perdiez toute validation offerte par l'attribut. En fin de compte, vous utilisez un mécanisme de validation pour résoudre un problème de mappage si vous utilisez l'attribut StringLength, où la réponse de Marcel Popescu à l'aide de l'attribut Column est une bien meilleure solution que d'utiliser les attributs de mappage pour définir le type l'attribut StringLength pour la validation.

Une autre option consiste à utiliser l'API fluide EF4 CTP5 et à définir le mappage de colonne dans l'événement OnModelCreating dans DbContext, par exemple.

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

En outre, il convient de noter que NText est un type de données déconseillé ( ntext, text et image (Transact-SQL) MS Books Online ) et il est recommandé d’utiliser NVarChar (MAX) à sa place.

6
nakchak

Je sais, c'est probablement un an trop tard, mais: 

Utilisation:

[StringLength(-1)] 

Cela créera un champ nText. J'ai réussi à stocker au moins 25 Ko dans ce domaine en utilisant La base de données Compact Edition 4.0. 

5
Johan Plogfeldt

Vous pouvez utiliser System.ComponentModel.DataAnnotations.Schema.ColumnAttribute

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

ou via l'API Fluent:

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

Acceptez le fait que TypeName = "ntext" semble fonctionner, même si je dois également ajouter:

[StringLength(Int32.MaxValue)]

pour que la longueur de chaîne par défaut de 128 ne soit pas gênante.

1
Steve Owen

Avez-vous essayé "text" minuscule? Pour cette discussion MSDN , le fournisseur de données est sensible à la casse.

1
Axarydax

Cette DataAnnotation fera également que Code-First génère une colonne nvarchar (MAX) dans SQL également :)

[StringLength(4010)]
1
Bohdan Lyzanets

Cette DataAnnotation fera que Code-First génère une colonne nvarchar (MAX) dans sql

[StringLength(1073741822)]

Je ne suis pas sûr que d’autres gros chiffres fassent de même ... J’ai eu celui-ci en utilisant la calculatrice et la spécification nvarchar (MAX).

Je l'ai essayé avec SQL Server 2005 Express ou non, mais pas avec CE

Je l'utilise et ça marche, mais j'aimerais savoir si c'est une bonne idée ou s'il me manque quelque chose ... existe-t-il un autre moyen de faire savoir par code que je veux nvarchar (MAX)?

1
Peto

Si vous ne souhaitez pas annoter toutes vos propriétés et que vous utilisez un EF contemporain, utilisez une convention:

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

Vous pouvez l'appeler depuis votre onModelCreating():

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

et tous vos strings deviendront automatiquement des colonnes ntext.

1
Gábor

Si vous effectuez add-migration et update-database en utilisant Package Manager, vous pouvez modifier la table create en ajoutant storeType comme suit:

       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);
0
hsobhy