EF 5 Code First DbMigration automation

江枫思渺然 提交于 2019-12-12 01:45:31

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!