¿Cómo puedo especificar que una propiedad debe generar una columna de TEXTO en lugar de un nvarchar (4000)


Estoy trabajando con la característica Code First de Entity Framework y estoy tratando de averiguar cómo puedo especificar los tipos de datos de columna que deben crearse cuando la base de datos se genera automáticamente.

Tengo un modelo 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; }
}

Cuando corro mi aplicación, se crea automáticamente una base de datos SQL CE 4.0 con el siguiente esquema:

Esquema DB

¡Hasta ahora, todo bien! Sin embargo, los datos que insertaré en las propiedades Body y BodyHtml son rutinariamente mayor que la longitud máxima permitida para el tipo de columna NVarChar, por lo que quiero que EF genere columnas Text para estas propiedades.

Sin embargo, parece que no puedo encontrar una manera de hacer esto! Después de bastante búsqueda en Google y lectura, traté de especificar el tipo de columna usando DataAnnotations, a partir de la información que se encuentra en esta respuesta :

using System.ComponentModel.DataAnnotations;

...

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

Esto genera la siguiente excepción (cuando se elimina la base de datos y se vuelve a ejecutar la aplicación):

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.

Pero no tengo idea de qué espacio de nombres o alias que debería especificar, y no pude encontrar nada que me dijera.

También intenté cambiar la anotación según esta referencia :

using System.Data.Linq.Mapping;

...

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

En este caso se crea una base de datos , pero la columna Body sigue siendo una NVarChar(4000), por lo que parece que se ignora la anotación.

¿Puede alguien ayudar? Esto parece que debería ser un requisito bastante común, sin embargo, mi búsqueda ha sido infructuosa!

Author: Community, 2011-02-04

12 answers

Aprecio el esfuerzo que se hizo en la respuesta existente, pero no la he encontrado realmente respondiendo a la pregunta... así que probé esto, y descubrí que

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

(el de System.ComponentModel.DataAnnotations) funcionará para crear una columna de tipo ntext.

(Mi problema con la respuesta aceptada es que parece indicar que debe cambiar el tipo de columna en la interfaz, pero la pregunta es cómo hacerlo programáticamente.)

 69
Author: Marcel Popescu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-06 13:38:24

Puede usar la siguiente anotación de datos y Code-First generará el tipo de datos de tamaño máximo que permite la base de datos. En el caso de Sql CE resulta en una columna ntext subyacente.

[MaxLength]

O usando la API EF 4.1 RC fluent...

protected override void OnModelCreating(ModelBuilder modelBuilder){
    modelBuilder.Entity<Article>()
        .Property(p => p.Body)
        .IsMaxLength();
}
 28
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 10:53:28

¿has probado ntext? Acabo de crear una base de datos SQL CE 4.0, y cuando agrego manualmente una columna a una tabla, noto que text no está disponible en la lista de tipos de datos mientras que ntext lo está. Al igual que puedes elegir nvarchar pero no varchar.

Desafortunadamente, el tamaño nvarchar más grande que puede elegir es 4000. Así que nvarchar(max) tampoco es una opción.

Hay ntext pero no text

 9
Author: Kristof Claes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-04 08:13:36

El problema con el uso del atributo string length, por ejemplo,

[StringLength(4010)]

Es que cualquier cadena > el número de caracteres definidos en el atributo activará una excepción de validación, que va en contra de cualquier razón por la que use un tamaño de campo no definido en una columna, o use un gran número en el atributo y pierda cualquier validación ofrecida por el atributo. En última instancia, está utilizando un mecanismo de validación para resolver un problema de asignación si utiliza el atributo StringLength, donde como Marcel La respuesta de Popescu que utiliza el atributo Column es una solución mucho mejor, ya que utiliza los atributos de asignación para definir el tipo, y aún así le permite usar el atributo StringLength para la validación.

Otra opción es usar la API EF4 CTP5 fluent y definir la asignación de columnas en el evento OnModelCreating en DbContext, por ejemplo,

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

También debe tenerse en cuenta que NText es un tipo de datos obsoleto (ntext, text, and image (Transact-SQL) MS Books Online) y el la recomendación es usar NVarChar (MAX) en su lugar

 5
Author: nakchak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-23 18:32:26

Lo sé, esto es probablemente un año demasiado tarde, pero:

Uso:

[StringLength(-1)] 

Esto creará un campo nText. Me las arreglé para almacenar al menos 25Kbytes en ese campo usando the Compact Edition 4.0 database (en inglés).

 5
Author: Johan Plogfeldt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-20 22:12:55

Puede utilizar System.ComponentModel.DataAnnotations.Schema.ColumnAttribute

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

O a través de Fluent API:

modelBuilder.Entity<YourEntityTypeHere>()
    .Property( e => e.Text)
    .HasColumnType("text");
 4
Author: Moes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-09 04:56:28

¿Has probado "text" en minúsculas? Para esta discusión de MSDN, el proveedor de datos distingue entre mayúsculas y minúsculas.

 1
Author: Axarydax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-04 07:18:22

Esta anotación de datos hará que el Código genere primero una columna nvarchar (MAX) en sql

[StringLength(1073741822)]

No estoy seguro si otros números grandes hacen lo mismo... Conseguí este usando la calculadora y la especificación nvarchar (MAX).

Lo he probado con SQL Server 2005 Express o no, pero no con CE

Lo estoy usando y funciona, pero me gustaría saber si es una buena idea o si me falta algo... ¿hay alguna otra forma de hacer que code-first sepa que quiero nvarchar(MAX)?

 1
Author: Peto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-16 15:38:00

Esta anotación de datos hará que el Código genere primero una columna nvarchar(MAX) en sql también:)

[StringLength(4010)]
 1
Author: Bohdan Lyzanets,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-17 14:03:58

Estoy de acuerdo en que TypeName = "ntext" parece funcionar, aunque también tengo que añadir:

[StringLength(Int32.MaxValue)]

Para detener la longitud de cadena predeterminada de 128 en el camino.

 1
Author: Steve Owen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-03 23:10:03

Si no desea anotar todas sus propiedades y usa un EF contemporáneo, use una convención:

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

Puedes llamarlo desde tu onModelCreating():

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

Y todos tus string s automáticamente se convertirán en ntext columnas.

 1
Author: Gábor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-19 22:37:05

En caso de que añada-migration y update-database usando Package Manager, puede modificar la tabla create añadiendo storeType de la siguiente manera:

       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
Author: hsobhy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-04 02:12:36