Creación del campo Entity Framework Code First Date

82

Estoy usando el método Entity Framework Code First para crear mi tabla de base de datos. El siguiente código crea una DATETIMEcolumna en la base de datos, pero quiero crear una DATEcolumna.

[DataType(DataType.Date)]
[DisplayFormatAttribute(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
public DateTime ReportDate { get; set; }

¿Cómo puedo crear una columna de tipo DATEdurante la creación de la tabla?

sfgroups
fuente

Respuestas:

22

La versión EF6 de la respuesta de David Roth es la siguiente:

public class DataTypePropertyAttributeConvention 
    : PrimitivePropertyAttributeConfigurationConvention<DataTypeAttribute>
{
    public override void Apply(ConventionPrimitivePropertyConfiguration configuration, 
        DataTypeAttribute attribute)
    {
        if (attribute.DataType == DataType.Date)
        {
            configuration.HasColumnType("Date");
        }
    }
}

Registre esto como antes:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Conventions.Add(new DataTypePropertyAttributeConvention());
}

Esto tiene el mismo resultado que el enfoque de Tyler Durden, excepto que usa una clase base EF para el trabajo.

Ricardo
fuente
164

Intente usar ColumnAttributedesde System.ComponentModel.DataAnnotations(definido en EntityFramework.dll):

[Column(TypeName="Date")]
public DateTime ReportDate { get; set; }
Ladislav Mrnka
fuente
1
Puede obtener un error, Sequence contains no matching elementsi apunta a una base de datos que no admite la fecha. SQL Server 2014 lo hace.
Jess
8
En EF6 necesitasusing System.ComponentModel.DataAnnotations.Schema;
JohnnyHK
10

Yo uso siguiente

    [DataType(DataType.Time)]
    public TimeSpan StartTime { get; set; }

    [DataType(DataType.Time)]
    public TimeSpan EndTime { get; set; }

    [DataType(DataType.Date)]
    [Column(TypeName = "Date")]
    public DateTime StartDate { get; set; }

    [DataType(DataType.Date)]
    [Column(TypeName = "Date")]
    public DateTime EndDate { get; set; }

Con Entity Framework 6 y SQL Server Express 2012 - 11.0.2100.60 (X64). Funciona perfectamente y genera tipos de columnas de fecha y hora en el servidor SQL

Irfan Ashraf
fuente
Tu solución funcionó. @YakoobHammourino funcionó. Tuve que usar ambas anotaciones [DataType(DataType.Date)]y [Column(TypeName = "Date")]como sugirió. Sin embargo, esta solución creó un formato de fecha yyyy-mm-dden lugar deMM-dd-yyyy
nam
9

Encontré que esto funciona muy bien en EF6.

Creé una convención para especificar mis tipos de datos. Esta convención cambia el tipo de datos DateTime predeterminado en la creación de la base de datos de datetime a datetime2. Luego aplica una regla más específica a cualquier propiedad que haya decorado con el atributo DataType (DataType.Date).

public class DateConvention : Convention
{
    public DateConvention()
    {
        this.Properties<DateTime>()
            .Configure(c => c.HasColumnType("datetime2").HasPrecision(3));

        this.Properties<DateTime>()
            .Where(x => x.GetCustomAttributes(false).OfType<DataTypeAttribute>()
            .Any(a => a.DataType == DataType.Date))
            .Configure(c => c.HasColumnType("date"));
    }
}

Luego registre la convención en su contexto:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    modelBuilder.Conventions.Add(new DateConvention());
    // Additional configuration....
}

Agregue el atributo a las propiedades de fecha y hora que desee que sean solo de fecha:

public class Participant : EntityBase
{
    public int ID { get; set; }

    [Required]
    [Display(Name = "Given Name")]
    public string GivenName { get; set; }

    [Required]
    [Display(Name = "Surname")]
    public string Surname { get; set; }

    [DataType(DataType.Date)]
    [Display(Name = "Date of Birth")]
    public DateTime DateOfBirth { get; set; }
}
Tyler Durden
fuente
1
¡Realmente una gran solución! Una cosa que quiero agregar para que quede completamente claro, que para poder usar esto, debe agregar el atributo en la propiedad de la fecha, por ejemplo, [Tipo de datos (Tipo de datos.Fecha)] Public DateTime IssueDate {get; conjunto; }
Stephen Lautier
@StephenLautier sí, debe agregar el atributo si desea poder usarlo solo para propiedades específicas de DateTime. En el código que agregué, muestro que también puede aplicar una regla general a todos sus tipos DateTime y luego una regla más específica a aquellos con la decoración DataType (DataType.Date). Espero que esto aclare cualquier confusión.
Tyler Durden
1
Buena solución, pero EF proporciona una clase base para hacer este trabajo por usted; consulte mi solución para obtener más detalles.
Richard
@Richard He votado a favor de tu solución porque tienes razón. Sin embargo, la razón por la que creé mi solución fue porque EF predetermina las propiedades DateTime para usar el tipo de datos datetime en SQL Server, no el tipo de datos datetime2 que es compatible con la propiedad .NET DateTime. Afortunadamente, EF core ha solucionado este problema ahora.
Tyler Durden
5

Si prefiere no para decorar sus clases con atributos, puede configurar esto en los DbContext's OnModelCreatingde esta manera:

public class DatabaseContext: DbContext
{
    // DbSet's

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // magic starts
        modelBuilder.Entity<YourEntity>()
                    .Property(e => e.ReportDate)
                    .HasColumnType("date");
        // magic ends

        // ... other bindings
    }
}
Stoyan Dimov
fuente
4

Además de usar ColumnAttribute, también puede crear una convención de atributos personalizados para DataTypeAttribute:

public class DataTypePropertyAttributeConvention : AttributeConfigurationConvention<PropertyInfo, PrimitivePropertyConfiguration, DataTypeAttribute>
{
    public override void Apply(PropertyInfo memberInfo, PrimitivePropertyConfiguration configuration, DataTypeAttribute attribute)
    {
        if (attribute.DataType == DataType.Date)
        {
            configuration.ColumnType = "Date";
        }
    }
}

Simplemente registre la convención en su método OnModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Conventions.Add(new DataTypePropertyAttributeConvention());
}
David Roth
fuente
Esto debería estar integrado en EF. ¡Gracias por compartir!
tugberk
Desafortunadamente, esto ha quedado obsoleto a partir de EF6 y ya no es válido.
Tyler Durden
1
EF6 proporcionó una nueva forma de hacer esto: consulte mi solución para obtener más detalles.
Richard
3

Esto es solo una mejora para el respuesta más votada por @LadislavMrnka sobre esta pregunta

si tienes mucho Date columnas, puede crear un atributo personalizado y luego usarlo cuando lo desee, esto producirá un código más limpio en las clases de Entidad

public class DateColumnAttribute : ColumnAttribute
{
    public DateColumnAttribute()
    {
        TypeName = "date";
    }
}

Uso

[DateColumn]
public DateTime DateProperty { get; set; }
Hakan Fıstık
fuente
-3

de la mejor manera usando el

[DataType(DataType.Date)]
public DateTime ReportDate { get; set; }

pero debes usar EntityFramework v 6.1.1

Yakoob Hammouri
fuente