SQL Server: Altering stored procedures using Fluent Migrator
Scenario
You have to add a column to an existing table. The stored procedures that work with the table have to be modified to account for the new column.
You make the changes to the table in a new migration class Up method. On that method you will also have to change the stored procedure in the DB to account for the new column. Here the nightmare begins: if you change your embedded stored procedure sql file to ALTER instead of CREATE, you will get an exception when running the migration for the first time, as the Stored Procedure you are trying to ALTER doesn't exist yet.
If you keep CREATE in the embedded sql file and DROP the existing stored procedure before executing it your Migrate Up would work, but not your Migrate Down, because you will be trying to create stored procedure that references a column that does not exist yet.
Solution
The way I resolved this was by keeping all the versions of the stored procedure sql files in the project and associating them with the Migration where they get executed by adding the Migration version to the sql file name.
Example
Here is an example:
- table named NewKey.
- add a column to that table named KeyID.
- a stored procedure in the DB and in my FM project called GetNewKey. That stored procedure does not reference KeyID, because the column didn't exist.
- make a copy of the sql file GetNewKey.sql, containng the CREATE statement that creates the GetNewKey stored procedure, and named that copy GetNewKey_201407091803.sql
Here is the migration code that does the rest:
01.[Migration(201407091803)]
02.public class NewKeyDatabaseMigration_201407091803 : Migration
03.{
04. /// <summary>
05. /// DB Changes
06. /// </summary>
07. public override void Up()
08. {
09. // Create new column
10. Alter.Table("NewKey")
11. .AddColumn("KeyID").AsInt64().NotNullable();
12.
13. // Drop previous SPs
14. Execute.Sql("DROP PROCEDURE [nks].[GetNewKey]");
15.
16. // Recreate SP using new scripts
17. Execute.EmbeddedScript("GetNewKey_201407091803.sql");
18. }
19.
20. /// <summary>
21. /// DB Changes Rollback
22. /// </summary>
23. public override void Down()
24. {
25. Delete.Column("KeyID")
26. .FromTable("NewKey");
27.
28. // Drop current SPs
29. Execute.Sql("DROP PROCEDURE [nks].[GetNewKey]");
30.
31. // Recreate SPs using previous script
32. Execute.EmbeddedScript("GetNewKey.sql");
33.
34. }
35.}
For convenience we used a DateTime YYYYMMDDHHMM time stamp as migration version: 201407091803