Створення поля першої дати Entity Framework Code


83

Я використовую метод Entity Framework Code First для створення таблиці бази даних. Наступний код створює DATETIMEстовпець у базі даних, але я хочу створити DATEстовпець.

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

Як я можу створити стовпець типу DATEпід час створення таблиці?

Відповіді:


22

Версія відповіді Девіда Рота на EF6 така:

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

Зареєструйте це як раніше:

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

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

Це має той самий результат, що і підхід Тайлера Дурдена, за винятком того, що для роботи використовується базовий клас EF.


165

Спробуйте використовувати ColumnAttributeз System.ComponentModel.DataAnnotations(визначеного в EntityFramework.dll):

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

1
Ви можете отримати помилку, Sequence contains no matching elementякщо ви вказуєте на БД, яка не підтримує дату. SQL Server 2014 робить.
Джесс

8
У EF6 вам потрібноusing System.ComponentModel.DataAnnotations.Schema;
JohnnyHK

11

Я використовую наступне

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

З Entity Framework 6 і SQL Server Express 2012 - 11.0.2100.60 (X64). Він чудово працює і генерує типи стовпців часу / дати на сервері sql


Ваше рішення спрацювало. @YakoobHammouriне працює. Мені довелося використовувати як анотації, так [DataType(DataType.Date)]і [Column(TypeName = "Date")]як ти запропонував. Однак це рішення , створене формат дати, yyyy-mm-ddна відміну відMM-dd-yyyy
Нама

9

Я знайшов це добре в EF6.

Я створив конвенцію про вказівку своїх типів даних. Ця умова змінює тип даних DateTime за замовчуванням у створенні бази даних із datetime на datetime2. Потім воно застосовує більш конкретне правило до будь-яких властивостей, які я прикрасив атрибутом 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"));
    }
}

Потім зареєструйте, а потім домовленість у своєму контексті:

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

Додайте атрибут до будь-яких властивостей DateTime, які хочете бути лише датою:

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

1
Дійсно чудове рішення! Одне, що я хочу додати, щоб бути повністю зрозумілим, що для його використання потрібно додати атрибут до властивості date, наприклад [DataType (DataType.Date)] public DateTime IssueDate {get; встановити; }
Стівен Лотьє

@StephenLautier так, ви повинні додати атрибут, якщо хочете мати можливість використовувати це лише для певних властивостей DateTime. У коді, який я додав, я показую, що ви також можете застосувати загальне правило до всіх типів DateTime, а потім більш конкретне правило до тих, що мають оздоблення DataType (DataType.Date). Сподіваюся, це усуває будь-яку плутанину.
Тайлер Дарден,

1
Хороше рішення, але EF надає базовий клас для виконання цієї роботи за вас - детальніше див. Моє рішення.
Річард,

@Richard Я проголосував за ваше рішення, бо ви праві. Причиною того, що я створив своє рішення, було те, що за замовчуванням EF властивості DateTime використовують тип даних datetime у SQL Server, а не тип даних datetime2, сумісний із властивістю .NET DateTime. На щастя, ядро ​​EF вирішило цю проблему зараз.
Тайлер

5

Якщо ви вважаєте за краще не прикрашати свої класи атрибутами, ви можете налаштувати це в параметрі DbContext" OnModelCreatingтак":

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

4

Окрім використання, ColumnAttributeви також можете створити власну конвенцію атрибутів для 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";
        }
    }
}

Просто зареєструйте конвенцію у своєму методі OnModelCreating:

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

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

Це слід вбудувати в EF. Дякую, що поділились!
тугберк

На жаль, ця версія застаріла на EF6 і більше не діє.
Тайлер Дурден,

1
EF6 дійсно запропонував новий спосіб зробити це - докладніше див. Моє рішення.
Річард

3

Це лише покращення для найбільш голосованої відповіді @LadislavMrnka на це питання

якщо у вас багато Dateстовпців, ви можете створити власний атрибут, а потім використовувати його, коли завгодно, це дасть більше чистого коду в класах Entity

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

Використання

[DateColumn]
public DateTime DateProperty { get; set; }

-3

найкращий спосіб за допомогою

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

але ви повинні використовувати EntityFramework v 6.1.1

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.