现在我们中的一些人已经在生产中运行了多年的Code First项目,并且已经积累了大量的迁移,有没有人遇到过大量的问题?是否有“太多迁移?”这样的事情。
如果是,那么补救措施是什么?一些警告: - 显然我们不能删除&重新生成生产数据库。 - 我们无法删除所有迁移,__ MigrationHistory,并创建一个新的Initial(在我的情况下),因为我们的许多迁移都有数据种子/更新,甚至可以调整生成的命令。
是否有方法/工具将迁移合并到较少的迁移中?这甚至会有所作为吗?
谢谢!
答案 0 :(得分:1)
根据ISHIDA的建议,我创建了一种结合迁移的方法示例。这绝不是唯一/正确的解决方案,也不能解决迁移膨胀是否有问题的问题,但它是一个良好的开端。
为了测试这个,我有一个带有2个表的控制台应用程序,它们是:
public class Account
{
[Required]
[StringLength(100)]
public string Id { get; set; }
[Required]
[StringLength(10)]
public string AccountNumber { get; set; }
public virtual List<Policy> Policies { get; set; }
}
public class Policy
{
[Required]
[StringLength(100)]
public string Id { get; set; }
[Required]
public int PolicyNumber { get; set; }
[Required]
public string AccountId { get; set; }
public virtual Account Account { get; set; }
}
有4次迁移创建了这些表,添加了数据,并将PolicyNumber的数据类型从string更改为int。假装这个程序是实时的,并且所有这些程序都在生产环境中运行。
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Accounts",
c => new
{
Id = c.String(nullable: false, maxLength: 100),
AccountNumber = c.String(nullable: false, maxLength: 10),
})
.PrimaryKey(t => t.Id);
}
public override void Down()
{
DropTable("dbo.Accounts");
}
}
public partial class SeedAccounts : DbMigration
{
readonly string[] accountIds = new string[] { "IdAcct101", "IdAcct102" };
public override void Up()
{
Sql($"INSERT INTO Accounts (Id, AccountNumber) VALUES ('{accountIds[0]}','101')");
Sql($"INSERT INTO Accounts (Id, AccountNumber) VALUES ('{accountIds[1]}','102')");
}
public override void Down()
{
Sql($"DELETE FROM Accounts WHERE ID = '{accountIds[0]}'");
Sql($"DELETE FROM Accounts WHERE ID = '{accountIds[1]}'");
}
}
}
public partial class AddPolicyTable : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Policies",
c => new
{
Id = c.String(nullable: false, maxLength: 100),
PolicyNumber = c.String(nullable: false, maxLength: 100),
AccountId = c.String(nullable: false, maxLength: 100),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Accounts", t => t.AccountId, cascadeDelete: true)
.Index(t => t.AccountId);
}
public override void Down()
{
DropForeignKey("dbo.Policies", "AccountId", "dbo.Accounts");
DropIndex("dbo.Policies", new[] { "AccountId" });
DropTable("dbo.Policies");
}
}
public partial class ChangeAndSeedPolicies : DbMigration
{
readonly string[] accountIds = new string[] { "IdAcct101", "IdAcct102" };
readonly string[] policyIds = new string[] { "IdPol101a", "IdPol101b", "IdPol102a" };
public override void Up()
{
AlterColumn("dbo.Policies", "PolicyNumber", c => c.Int(nullable: false));
Sql($"INSERT INTO Policies (Id, AccountId, PolicyNumber) VALUES ('{policyIds[0]}', '{accountIds[0]}', '10101')");
Sql($"INSERT INTO Policies (Id, AccountId, PolicyNumber) VALUES ('{policyIds[1]}', '{accountIds[0]}', '10102')");
Sql($"INSERT INTO Policies (Id, AccountId, PolicyNumber) VALUES ('{policyIds[2]}', '{accountIds[1]}', '10201')");
}
public override void Down()
{
Sql($"DELETE FROM Policies WHERE ID = '{policyIds[0]}'");
Sql($"DELETE FROM Policies WHERE ID = '{policyIds[1]}'");
Sql($"DELETE FROM Policies WHERE ID = '{policyIds[2]}'");
AlterColumn("dbo.Policies", "PolicyNumber", c => c.String(nullable: false, maxLength: 100));
}
}
以下是项目主要代码:
using (var dc = new DataContext())
{
foreach (var account in dc.Accounts.OrderBy(q => q.AccountNumber).ToList())
{
Console.WriteLine("Account " + account.AccountNumber);
foreach (var policy in account.Policies)
Console.WriteLine(" Policy " + policy.PolicyNumber);
}
}
DataContext类:
public class DataContext : DbContext
{
public DataContext() : base("DefaultConnection") { }
public DbSet<Account> Accounts { get; set; }
public DbSet<Policy> Policies { get; set; }
}
输出结果为:
Account 101
Policy 10101
Policy 10102
Account 102
Policy 10201
很简单。现在我想将这些迁移合并为一个。记住:
这些是我遵循的步骤:
要验证新迁移确实完成了旧迁移所做的一切(对于新环境或测试),只需删除数据库中的所有表(包括__MigrationHistory),运行&#34; update-database&#34;在PMC中,看它是否运行。
这就是我的新迁移:
public partial class CombinedMigration : DbMigration
{
readonly string[] accountIds = new string[] { "IdAcct101", "IdAcct102" };
readonly string[] policyIds = new string[] { "IdPol101a", "IdPol101b", "IdPol102a" };
public override void Up()
{
CreateTable(
"dbo.Accounts",
c => new
{
Id = c.String(nullable: false, maxLength: 100),
AccountNumber = c.String(nullable: false, maxLength: 10),
})
.PrimaryKey(t => t.Id);
Sql($"INSERT INTO Accounts (Id, AccountNumber) VALUES ('{accountIds[0]}','101')");
Sql($"INSERT INTO Accounts (Id, AccountNumber) VALUES ('{accountIds[1]}','102')");
CreateTable(
"dbo.Policies",
c => new
{
Id = c.String(nullable: false, maxLength: 100),
PolicyNumber = c.String(nullable: false, maxLength: 100),
AccountId = c.String(nullable: false, maxLength: 100),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Accounts", t => t.AccountId, cascadeDelete: true)
.Index(t => t.AccountId);
AlterColumn("dbo.Policies", "PolicyNumber", c => c.Int(nullable: false));
Sql($"INSERT INTO Policies (Id, AccountId, PolicyNumber) VALUES ('{policyIds[0]}', '{accountIds[0]}', '10101')");
Sql($"INSERT INTO Policies (Id, AccountId, PolicyNumber) VALUES ('{policyIds[1]}', '{accountIds[0]}', '10102')");
Sql($"INSERT INTO Policies (Id, AccountId, PolicyNumber) VALUES ('{policyIds[2]}', '{accountIds[1]}', '10201')");
}
public override void Down()
{
// Each prior "Down" section was added in reverse order.
Sql($"DELETE FROM Policies WHERE ID = '{policyIds[0]}'");
Sql($"DELETE FROM Policies WHERE ID = '{policyIds[1]}'");
Sql($"DELETE FROM Policies WHERE ID = '{policyIds[2]}'");
AlterColumn("dbo.Policies", "PolicyNumber", c => c.String(nullable: false, maxLength: 100));
DropForeignKey("dbo.Policies", "AccountId", "dbo.Accounts");
DropIndex("dbo.Policies", new[] { "AccountId" });
DropTable("dbo.Policies");
Sql($"DELETE FROM Accounts WHERE ID = '{accountIds[0]}'");
Sql($"DELETE FROM Accounts WHERE ID = '{accountIds[1]}'");
DropTable("dbo.Accounts");
}
}
警告:如果您的任何迁移具有创建新DC的.NET代码并执行某些db更新,那么在迁移组合时这些可能无效。例如,如果迁移1添加了Account表,并且迁移2使用.NET代码将记录插入到Account中,则它将在组合迁移中崩溃,因为尚未创建Account技术。用Sql(&#39; INSERT INTO ...&#34;)语句替换这些语句将解决这个问题。