Создание поля Entity Framework Code First Date

83

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

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

Как я могу создать столбец типа DATEво время создания таблицы?

sfgroups
источник

Ответы:

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

Попробуйте использовать ColumnAttributefrom 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
nam
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
Действительно отличное решение! Одна вещь, которую я хочу добавить, чтобы было совершенно ясно, что для того, чтобы использовать это, вам нужно добавить атрибут в свойство даты, например [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 устранило эту проблему.
Tyler Durden
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. Спасибо, что поделился!
tugberk
К сожалению, это устарело с EF6 и больше не действует.
Tyler Durden
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

Якуб Хаммури
источник