Possible to default DateTime field to GETDATE() with Entity Framework Migrations?
I added EntityFramework.Migrations (Beta 1) to an existing Code-First app that is going through some changes (for both migration capabilities and more fine-tuning of the tables I am generating from my code-first API) and ran into the GETDATE() scenario.
I was already using a custom initializer class in my DbContext to run SQL scripts to set some fields and create indexes in my database. A handful of my AlterTable scripts are primary just to setup fields with default values(such as certain DateTime fields being set to GETDATE()). I was really hoping EntityFramework.Migrations would have an answer for this since you can easily specify defaultValue, but so far I'm not seeing one.
Any ideas? I was really hoping that doing the following would magically work. (It is 'magic unicorn', after all)
DateCreated = c.DateTime(nullable: false, defaultValue: DateTime.Now)
Unfortunately, and logically, it set my default value to the time when the Update-Database
command was executed.
Solution 1:
You can use
DateCreated = c.DateTime(nullable: false, defaultValueSql: "GETDATE()")
Usage:
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);
...
Update 2012-10-10:
As requested by Thiago in his comment, I add a little extra context.
The code above is a migration-file generated by EF Migrations by running Add-Migration MyMigration
as a command in the package manager console. The generated code is based on the models in the DbContext associated with migrations. The answer suggests that you modify the generated script so that a default value is added when the database is created.
You can read more about Entity Framework Code First Migrations here.
Solution 2:
I recently ran in to this issue in EF6 (since they still haven't fixed it). The easiest way I found to do it without having to manually modify the Migration class is to override the CodeGenerator in your Configuration class.
By creating a class that implements MigrationCodeGenerator and then overriding the Generate method you can iterate through all of the operations and apply what ever modifications you want.
Once your modifications have been made, you can then initialize your the CSharpMigrationCodeGenerator and return its default value.
public class ExtendedMigrationCodeGenerator : MigrationCodeGenerator
{
public override ScaffoldedMigration Generate(string migrationId, IEnumerable<MigrationOperation> 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<Project.Models.Context.DatabaseContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = @"Migrations";
this.CodeGenerator = new ExtendedMigrationCodeGenerator();
}
}
I hope this helps