问题
I'm using EF 5 with the Code First Approach.
I'm having trouble setting the default DateTime
value of a column to a (getdateutc())
What I want to do is have EF set up tables with this value speficied, and the only way I've found that it's possible is to use DbMigrations
(Up and Down methods). Are the any other ways ?
I have a base class looking like this
public abstract class BASE_AUDITED : BASE
{
[IgnoreDataMember, IgnoreMap]
public DateTime Created { get; set; }
[IgnoreDataMember, IgnoreMap]
public DateTime Modified { get; set; }
[MaxLength(50)]
[IgnoreDataMember, IgnoreMap]
public string CreatedBy { get; set; }
[MaxLength(50)]
[IgnoreDataMember, IgnoreMap]
public string ModifiedBy { get; set; }
}
public abstract class BASE
{
[IgnoreMap]
public int id { get; set; }
}
And a bunch of classes inheriting from it.
What I'd like to do is be able to access the model (using fluentAPI
for mapping)in the DBMigrations Up method, and write a loop there to take care of all the the objects inheriting from Base_audited
In other words I'm trying to avoid writing following code for each and every object I add,
AlterColumn("T70_AccountService.CONTACT", "TestClmn", c => c.DateTime(nullable: false, defaultValueSql: "(getutcdate())"));
But rather have smth like this
var types = ReflectionHelper.TypesImplementingInterface(typeof (BASE_AUDITED));
foreach (var type in types)
{
var tableName = Context.FindTableNameFor(type);
AlterColumn(tableName , "Created", c => c.DateTime(nullable: false, defaultValueSql: "(getutcdate())"));
AlterColumn(tableName , "Modified", c => c.DateTime(nullable: false, defaultValueSql: "(getutcdate())"));
}
In short - I cannot find what table is the object mapped to in the DbMigrations Up method..
var tableName = Context.FindTableNameFor(type);
回答1:
The solution I've implemented, and that seems to work fine with some overhead (of recreating contrains) is to use the "Seed
" method of the migration configuration:
protected override void Seed(AccountServiceEntities context)
{
// This method will be called after migrating to the latest version.
#region SET Defaults for Audit Fields
var types = ReflectionHelper.GetEnumerableOfType<BASE_AUDITED>();
foreach (var type in types)
{
var method = typeof(ContextExtensions).GetMethod("GetTableName");
var generic = method.MakeGenericMethod(type.GetType());
var table = generic.Invoke(this, new object[] { context });
var constraintName = string.Format("DF__{0}__", type.GetType().Name);
CreateDefaultCronstraint(context, table, constraintName, "Created");
CreateDefaultCronstraint(context, table, constraintName, "Modified");
}
#endregion...
And here's the modified Context extentions class that extract the table name from the Context public static class ContextExtensions {
public static string GetTableName<T>(this DbContext context) where T : class
{
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
return objectContext.GetTableName2<T>();
}
public static string GetTableName2<T>(this ObjectContext context) where T : class
{
var sql = context.CreateObjectSet<T>().ToTraceString();
var regex = new Regex("FROM (?<table>.*) AS");
var match = regex.Match(sql);
var table = match.Groups["table"].Value;
return table;
}
}
来源:https://stackoverflow.com/questions/13294780/ef-5-code-first-dbmigration-automation