I have a local dev environment and database that I update automatically with Update-Database
, and then apply the migrations to the production environment with scripts (produced with Update-Database -Script
).
In my latest update, I added a new column, and then in the Up() method of the migration, I added the necessary code to populate the column. The migration then looked like this:
public partial class AddPaymentOptionToPledge : DbMigration
{
public override void Up()
{
AddColumn("dbo.tblPledge", "PaymentOptionId", c => c.Int());
Sql(@"UPDATE dbo.tblPledge
SET dbo.tblPledge.PaymentOptionId = (SELECT ID FROM dbo.tblPaymentOption
WHERE dbo.tblPaymentOption.UserID = dbo.tblPledge.UserID
AND dbo.tblPaymentOption.IsDefault = 1)
WHERE dbo.tblPledge.PaymentOptionId IS NULL
AND EXISTS (SELECT ID FROM dbo.tblPaymentOption
WHERE dbo.tblPaymentOption.UserID = dbo.tblPledge.UserID
AND dbo.tblPaymentOption.IsDefault = 1)");
}
public override void Down()
{
DropColumn("dbo.tblPledge", "PaymentOptionId");
}
}
I had no problem running Update-Database
locally, but when it came to applying the migration to production, I got the error Invalid column name 'PaymentOptionId'
. The script that EF produced (which I was applying) was this:
ALTER TABLE [dbo].[tblPledge]
ADD [PaymentOptionId] [int]
UPDATE dbo.tblPledge
SET dbo.tblPledge.PaymentOptionId = (SELECT ID
FROM dbo.tblPaymentOption
WHERE dbo.tblPaymentOption.UserID = dbo.tblPledge.UserID
AND dbo.tblPaymentOption.IsDefault = 1)
WHERE dbo.tblPledge.PaymentOptionId IS NULL --<ERROR HERE>--
AND EXISTS (SELECT ID
FROM dbo.tblPaymentOption
WHERE dbo.tblPaymentOption.UserID = dbo.tblPledge.UserID
AND dbo.tblPaymentOption.IsDefault = 1)
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201611101848224_AddPaymentOptionToPledge', N'J127T.PaymentGateway.DataModel.MigrationConfiguration', 0x1F8B0800000000000400E...8C8297E790610000 , N'6.1.3-40302')
To get it to work, I had to split the script into two steps, first running ALTER TABLE
. After that, the rest of the script ran fine.
My attraction to EF Code First is that it automates much of the db admin, but in this case I had to manually tweak the script to get it to work. Is this a common requirement with EF, or should I have written the update statement in a more robust way so that it wouldn't cause a problem when applied as part of a migration?