我正在尝试创建一个自定义迁移步骤来清理我们数据库中的一些默认值。基本上我们有一些数据要么无效,要么需要更新,而在其他情况下,这些数据根本不存在。该系统安装在多台服务器上,大量数据是一次性手动添加的,因此很难知道哪个服务器有哪些数据。
我想做的是创建一个迁移步骤来清理它。如果表中不存在此值,我需要将其插入。但是,如果它确实存在,那么我要么更新它,要么删除它然后插入它。我很难弄清楚如何做到这一点。
Add-Migration DataCleanup
创建迁移步骤
public partial class DataCleanup : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Blogs",
columns: new[] { "BlogId", "Url" },
values: new object[] { 4, "http://sample4.com" });}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "Blogs",
keyColumn: "BlogId",
keyValue: 4);
}
}
如果该行以前不存在,这将起作用,但如果该行确实存在,那么我将需要更新以确保该值是正确的值。我不担心主键,因为这是一个引用表,它们“应该”相同。
我能想到的唯一其他选择是对这些表运行截断,然后再运行插入。
migrationBuilder.Sql("TRUNCATE TABLE [Blogs]", true);
向下注意
我倾向于完全不能做羽绒服。在我运行之前,无法知道这台服务器处于什么状态。
最佳答案
首先,我无法在表上进行截断,因为设置了外键,这意味着那是行不通的。
我最后做了一堆 sql 插入,检查第一个行是否存在,如果不存在,我们就插入它。
migrationBuilder.Sql("INSERT INTO IdentityResources (Description, DisplayName, Emphasize, Enabled, Name, Required, ShowInDiscoveryDocument) " +
"SELECT 'Your email address', 'User email', 1, 1, 'email', 0, 1 " +
"WHERE NOT EXISTS(SELECT * " +
"FROM IdentityResources " +
"WHERE name = 'email'); ", true);
当我需要添加第一个插入的 key 时,事情变得有点复杂。
migrationBuilder.Sql("INSERT INTO IdentityClaims (IdentityResourceId, Type) " +
"SELECT id, 'email' " +
"FROM IdentityResources " +
"WHERE Name = 'email' " +
"AND NOT EXISTS(SELECT * " +
"FROM [IdentityClaims] " +
"WHERE type = 'email')");
这一切最终都成功了。新安装的系统会构建适当的数据库,每个人都会得到更新,以确保他们至少拥有所需的数据。
不幸的是,删除不需要的数据将不得不再等一天。
关于c# - 使用 Entity Framework 向现有数据库添加或更新数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54553668/