Custom logic in code EF6 SqlServerMigrationSqlGenerator not working

I am trying to set the SQL default value for a computed column named "Duration" in table "dbo.Table1" when I move Entity Framework 6 for the first time using the SqlServerMigrationSqlGenerator class.

I tried setting this in the Generate methods for AddColumnOperation as well as CreateTableOperation. Although the code in the Generate method for the column never fires, the code in the Generate table section does fire and throws an error saying the following. (the EndTime column is a column in the dbo.Table1 table as well as StartTime)

In this context, the name "EndTime" is not permitted. Valid constant expressions, constant expressions, and (in some contexts) variables. Column names are not allowed.

Question . How can I make this work in any of the Generate methods in the code below?

        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);
        }

    }

      

UPDATE 1 :

I used another simple approach to add my custom logic to modify database objects using ExecuteSqlCommand. Just follow these steps to use it in your situation.

  • create a custom script to modify or create a database object
  • execute command in Seed method for each custom script
  • make sure the ExecuteSqlCommand statement is placed at the end of the Seed method, and also the context.SaveChanges () method is called before the code for custom scripts in case there is a dependency on the seed data

    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)); ");
    
    }
    
          

+3


source to share


1 answer


This is not a limitation of EF, but of the database itself - you cannot reference other columns in the default specification. Instead, I would recommend that you write a stored procedure to add new Table1 objects and then render with a smooth api as per the article .



+2


source







All Articles