Возможно ли по умолчанию использовать поле 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"); 
  • Entity Framework Code First Fluent Api: добавление индексов в столбцы
  • Преобразование Entity Framework / Linq EXpression из строки в int
  • Entity Framework / SQL2008 - Как автоматически обновлять поля LastModified для объектов?
  • Безопасность платформы Entity Framework
  • Как реализовать Единицу работы, которая работает с EF и NHibernate
  • Есть ли в Entity Framework 4 Code First поддержка генераторов идентификаторов, таких как NHibernate?
  • Entity Framework: Где я могу расширить CSDL / MSL?
  • EF Code First: Как я могу увидеть свойство EntityValidationErrors из консоли пакета nuget?
  • Результат запроса нельзя перечислить более одного раза
  • Объект нельзя удалить, поскольку он не найден в ObjectStateManager
  • Как установить значение по умолчанию для POCO в EF CF?
  • Давайте будем гением компьютера.