Возможно ли по умолчанию использовать поле DateTime для GETDATE () с миграциями Entity Framework?

Я добавил EntityFramework.Migrations (бета-версия 1) в существующее приложение Code-First, которое проходит через некоторые изменения (как для возможностей миграции, так и для более тонкой настройки таблиц, которые я генерирую из моего первого кода кода) и столкнулся с GETDATE ().

Я уже использовал собственный class инициализатора в своем DbContext для запуска SQL-скриптов для установки некоторых полей и создания индексов в моей базе данных. Несколько моих скриптов AlterTable являются первичными для установки полей со значениями по умолчанию (например, для определенных полей DateTime устанавливается значение GETDATE ()). Я действительно надеялся, что EntityFramework.Migrations будет отвечать за это, так как вы можете легко указать defaultValue, но пока я его не вижу.

Есть идеи? Я действительно надеялся, что выполнение следующего будет волшебным образом работать. (В конце концов, это «волшебный единорог»)

DateCreated = c.DateTime(nullable: false, defaultValue: DateTime.Now) 

К сожалению, и логически, оно установило мое значение по умолчанию на время выполнения команды Update-Database .

Вы должны использовать собственный скрипт SQL в методе Up для установки значения по умолчанию:

 Sql("ALTER TABLE TableName ADD CONSTRAINT ConstraintName DEFAULT GETDATE() FOR ColumnName"); 

Установка значения по умолчанию в коде допускает только статические значения – нет функций уровня базы данных.

В любом случае настройка его в конструкторе POCO является правильным способом, если вы собираетесь использовать код в первую очередь. Также, если вы хотите установить значение в приложении для некоторых специальных случаев, вы не можете использовать значение по умолчанию в базе данных, потому что значение по умолчанию в базе данных требует либо DatabaseGeneratedOption.Identity либо DatabaseGeneratedOption.Computed . Обе эти опции позволяют устанавливать свойство только в базе данных.

Редактировать:

Поскольку продукт все еще находится в разработке, мой ответ больше недействителен. Проверьте @gius ответ для фактического способа достижения этого требования, используя defaultValueSql (он не был доступен в EF Migrations Beta 1, но был добавлен в EF 4.3 Beta 1, который уже включает в себя миграции).

Вы можете использовать

 DateCreated = c.DateTime(nullable: false, defaultValueSql: "GETDATE()") 

Применение:

 public partial class MyMigration : DbMigration { public override void Up() { CreateTable("dbo.Users", c => new { Created = c.DateTime(nullable: false, defaultValueSql: "GETDATE()"), }) .PrimaryKey(t => t.ID); ... 

Обновление 2012-10-10:

По просьбе Тьяго в своем комментарии я добавляю немного дополнительного контекста.

Приведенный выше код является файлом миграции, сгенерированным EF Migrations, запустив Add-Migration MyMigration в качестве команды в консоли диспетчера пакетов. Сгенерированный код основан на моделях в DbContext, связанных с миграциями. Ответ предполагает, что вы изменяете сгенерированный скрипт так, чтобы при создании базы данных добавлялось значение по умолчанию.

Здесь вы можете узнать больше о Первых Миграх Entity Framework Code.

Недавно я столкнулся с этим вопросом в EF6 (так как они все еще не исправили его). Самый простой способ, которым я нашел это, без необходимости вручную модифицировать class Migration, – переопределить CodeGenerator в вашем classе конфигурации.

Создав class, который реализует MigrationCodeGenerator, а затем переопределяет метод Generate, вы можете выполнять итерацию всех операций и применять любые изменения, которые вы хотите.

После внесения изменений вы можете инициализировать свой CSharpMigrationCodeGenerator и вернуть значение по умолчанию.

 public class ExtendedMigrationCodeGenerator : MigrationCodeGenerator { public override ScaffoldedMigration Generate(string migrationId, IEnumerable operations, string sourceModel, string targetModel, string @namespace, string className) { foreach (MigrationOperation operation in operations) { if (operation is CreateTableOperation) { foreach (var column in ((CreateTableOperation)operation).Columns) if (column.ClrType == typeof(DateTime) && column.IsNullable.HasValue && !column.IsNullable.Value && string.IsNullOrEmpty(column.DefaultValueSql)) column.DefaultValueSql = "GETDATE()"; } else if (operation is AddColumnOperation) { ColumnModel column = ((AddColumnOperation)operation).Column; if (column.ClrType == typeof(DateTime) && column.IsNullable.HasValue && !column.IsNullable.Value && string.IsNullOrEmpty(column.DefaultValueSql)) column.DefaultValueSql = "GETDATE()"; } } CSharpMigrationCodeGenerator generator = new CSharpMigrationCodeGenerator(); return generator.Generate(migrationId, operations, sourceModel, targetModel, @namespace, className); } } internal sealed class Configuration : DbMigrationsConfiguration { public Configuration() { AutomaticMigrationsEnabled = false; MigrationsDirectory = @"Migrations"; this.CodeGenerator = new ExtendedMigrationCodeGenerator(); } } 

надеюсь, это поможет

Создать миграцию:

 public partial class Table_Alter : DbMigration { public override void Up() { AddColumn("dbo.tableName", "columnName", c => c.DateTime(nullable: false, defaultValueSql: "GETDATE()")); } public override void Down() { DropColumn("dbo.tableName", "columnName"); } } 

Для существующих записей он установит дату-время, когда вы запустите команду « Update-Database , для новых записей будет установлено время и время создания

В качестве альтернативы, если ваши объекты наследуются от общего интерфейса, вы можете переопределить метод SaveChanges в DbContext и установить или обновить свойства в этот момент (отлично подходит для «Дата создания и дата последнего изменения»)

Это самый простой способ.

Сначала добавьте DatabaseGeneratedOption.Computed DataAnnotion в вашу собственность

и теперь вы можете изменить SqlServerMigrationSqlGenarator , переопределить метод Genarate и установить DefaultValueSql = "GETDATE()" or "GETUTCDATE()";

Улучшение: проверьте, существует ли ограничение:

 Sql(@" if not exists ( select * from sys.all_columns c join sys.tables t on t.object_id = c.object_id join sys.schemas s on s.schema_id = t.schema_id join sys.default_constraints d on c.default_object_id = d.object_id where d.name = 'DF_ThubOutputEmail_Created' ) begin ALTER TABLE dbo.ThubOutputEmails ADD CONSTRAINT DF_ThubOutputEmail_Created default getdate() for Created; end"); 
  • Зачем повторно инициировать DbContext при использовании Entity Framework?
  • Обновление отношений при сохранении изменений объектов EF4 POCO
  • Entity Framework Code First Fluent Api: добавление индексов в столбцы
  • Преобразование String в Int в EF 4.0
  • Entity Framework 4 выборочно ленивые свойства загрузки
  • Как отключить сущность из контекста в Entity Framework?
  • Самый эффективный метод дерева привязки с использованием Entity Framework
  • Как реализовать Единицу работы, которая работает с EF и NHibernate
  • Указанный член типа не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, сущности и свойства навигации сущности
  • Entity Framework объединяет 3 таблицы
  • Добавление сложных типов хранимых процедур в Entity Framework
  • Interesting Posts

    Как убить все запущенные приложения в Android?

    Почему большой локальный массив разбивает мою программу, но глобальный – нет?

    Почему int num = Integer.getInteger («123») бросает NullPointerException?

    Модальный диалог

    Создание символов 256-цветного и линейного рисования работает в PuTTY

    Управление навигационной панелью и обратной кнопкой панели инструментов из fragmentа в андроиде

    Подавление вывода windows команды функции

    Сделать безопасный оператор $ {} XSS безопасным в Struts 2 (так же, как и гобелен)

    Ошибка Android Studio Gradle: несколько файлов dex определяют

    Класс не является абстрактным и не отменяет абстрактного метода

    Возвращает объект «NULL», если результат поиска не найден

    Как скопировать значение из classа X в class Y с тем же именем свойства в c #?

    Мое регулярное выражение подходит слишком много. Как заставить его остановиться?

    Получение измененного имени из измененного имени

    Удалить разрыв строки в TabLayout

    Давайте будем гением компьютера.