代码优先的自定义逻辑EF6 SqlServerMigrationSqlGenerator无法正常工作

时间:2015-04-17 14:57:30

标签: entity-framework sql-server-2012 ef-code-first

我试图在表'dbo.Table1'中为名为'Duration'的计算列设置默认值SQL,在代码优先的Entity Framework 6中通过SqlServerMigrationSqlGenerator类进行迁移。

我尝试在AddColumnOperation的Generate方法和CreateTableOperation中设置它。虽然Generate method for column下的代码永远不会触发,但Generate table下的代码会触发并抛出错误,说明以下内容。 (EndTime列是表dbo.Table1中的一列,因此是StartTime)

  

在此上下文中不允许使用名称“EndTime”。有效表达式   是常量,常量表达式和(在某些上下文中)变量。   不允许使用列名。

问题:我怎样才能在下面的代码中的任何一个Generate方法中使用它?

        internal class CustomImplForSqlServerMigration: SqlServerMigrationSqlGenerator {
        protected override void Generate(AlterColumnOperation alterColumnOperation) {

            base.Generate(alterColumnOperation);
        }
        protected override void Generate(AddColumnOperation addColumnOperation) {


            if (addColumnOperation.Table == "dbo.Table1" && addColumnOperation.Column.Name == "Duration") {
                addColumnOperation.Column.DefaultValueSql = "(CAST(CAST(EndTime AS DATETIME) - CAST(StartTime AS DATETIME) AS TIME))";
            }
            base.Generate(addColumnOperation);
        }

        protected override void Generate(CreateTableOperation createTableOperation) {


            if (createTableOperation.Name == "dbo.Table1") {
                foreach(ColumnModel cm in createTableOperation.Columns) {
                    if (cm.Name == "Duration") {
                        cm.DefaultValueSql = "(CAST(CAST(EndTime AS DATETIME) - CAST(StartTime AS DATETIME) AS TIME))";
                    }
                }
            }
            base.Generate(createTableOperation);
        }

    }

更新1

我使用另一种简单的方法来添加我的自定义逻辑,以使用ExecuteSqlCommand修改数据库对象。只需按照以下步骤在您的情况下使用它。

  • 提出了用于修改或创建数据库对象的自定义脚本
  • 在每个自定义脚本的种子方法中执行命令
  • 确保将ExecuteSqlCommand语句放在Seed方法的末尾,并且在依赖种子数据的情况下,在自定义脚本的代码之前调用context.SaveChanges()方法

    protected override void Seed(EfCodeFirst.ShiftsDb context)
    {
       //Write your seed data statements
    
       //call SaveChanges in case your custom script depends
       //on some seed data
       context.SaveChanges();
    
        //include your custom scripts like ALTER TABLE 
        //or CREATE PROCEDURE or anything else
        //use a ExecuteSqlCommand for every custom script
        context.Database.ExecuteSqlCommand(@"ALTER TABLE ShiftTypes DROP COLUMN Duration; 
         ALTER TABLE TABLE1 ADD Duration AS (CAST(CAST(EndTime AS DATETIME) - 
          CAST(StartTime AS DATETIME) AS TIME)); ");
    
    }
    

1 个答案:

答案 0 :(得分:2)

这不是EF的限制,而是数据库本身的限制 - 您不能引用默认值规范中的其他列。我建议你改为编写用于插入新的Table1实体的存储过程,然后根据article使用流畅的api进行映射。