如何使用 entity framework 代码优先实现在迁移时使用唯一值更新每一行
HowTo update every row with unique value on migration using entity framework code first implementation
我正在寻找一种适当的方法来扩展现有数据库,基于 entity framework 6 代码优先实现,并为 table 中的每个现有行的新字段添加唯一值。
到目前为止,我已经创建了一个添加新字段的迁移。
Up 方法如下所示:
Public Overrides Sub Up()
AddColumn("dbo.Customers", "UniqueCode", Function(c) c.String(unicode:=False))
End Sub
我卡在新字段应填充唯一(计算)值的位置。为简单起见,假设数据库中的每个现有行都应在迁移时分配一个 GUID。
使用这样的 SQL 语句将更新具有相同 GUID 的所有行。但我需要它对每一行都是唯一的。
Sql("Update dbo.Customers SET UniqueCode = '" & Guid.NewGuid().ToString)
在 Up 方法中使用 foreach 似乎有点不对...在这种情况下最佳做法是什么?
另外:我用的数据库是access,所以不能用newid()或random()。 GUID 旨在作为以编程方式计算的值的虚拟对象。它将是客户的一些其他属性的散列值。所以必须用迁移来计算和更新。
如果您的数据库服务器是 SQL 服务器,您可以使用在数据库服务器
上生成 GUID 的内置 newid()
函数
https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql
查询将是
Update dbo.Customers SET UniqueCode = newid()
如果是 SQLite 数据库,请使用 random()
函数。
我发现以下方法最适合我的情况。我建议将数据库和数据更改拆分为 2 个迁移,这样您就可以使用框架进行所有更改,并完全兼容上下兼容。
这里是我的方法的详细信息:
根据 Bradley Uffner 的建议,我循环遍历数据并逐行更新它。但是,在同一个迁移中执行此操作会引发错误:
The model backing the 'DbContext' context has changed since the database was created. Consider using Code First Migrations to update the database.
在迁移过程中使用 DbContext 会导致状态不一致。该模型已经处于迁移后状态,但数据库在表中仍具有迁移前状态。模型和数据库不匹配,导致出现上述错误。为了完成这项工作,我将不得不禁用模型检查。
参考:
在上面的线程中,我发现了将数据库更改与数据更改分开的建议。这正是我所做的。
我创建了一个迁移来更新数据库
Public Overrides Sub Up()
AddColumn("dbo.Customers", "WebCode", Function(c) c.String(unicode := false))
End Sub
Public Overrides Sub Down()
DropColumn("dbo.Customers", "WebCode")
End Sub
运行 Update-Database
命令。然后创建第二个迁移以进行数据更改。 Up
和 Down
方法在创建时将为空。这是我用来逐行更新数据的代码。
Public Overrides Sub Up()
Dim DbContext As New Data.DbContext
For Each customer In DbContext.Customers.Where(Function(x) String.IsNullOrEmpty(x.WebCode))
customer.WebCode = GetWebCode(customer)
Next
DbContext.SaveChanges()
End Sub
Public Overrides Sub Down()
Dim DbContext As New Data.DbContext
For Each customer In DbContext.Customers
customer.WebCode = Nothing
Next
MyDbContext.SaveChanges()
End Sub
有些人可能会争论在 Down 方法中使用简单的 SQL,例如
SQL("Update dbo.Customers SET WebCode = NULL")
效率更高。我已经尝试过了,但是在 JetEntityFrameworkProvider.JetMigrationSqlGenerator.GenerateSqlStatmentConcrete
遇到了一个我无法找到并修复的错误。它使 Visual Studio 崩溃。
我正在寻找一种适当的方法来扩展现有数据库,基于 entity framework 6 代码优先实现,并为 table 中的每个现有行的新字段添加唯一值。
到目前为止,我已经创建了一个添加新字段的迁移。
Up 方法如下所示:
Public Overrides Sub Up()
AddColumn("dbo.Customers", "UniqueCode", Function(c) c.String(unicode:=False))
End Sub
我卡在新字段应填充唯一(计算)值的位置。为简单起见,假设数据库中的每个现有行都应在迁移时分配一个 GUID。
使用这样的 SQL 语句将更新具有相同 GUID 的所有行。但我需要它对每一行都是唯一的。
Sql("Update dbo.Customers SET UniqueCode = '" & Guid.NewGuid().ToString)
在 Up 方法中使用 foreach 似乎有点不对...在这种情况下最佳做法是什么?
另外:我用的数据库是access,所以不能用newid()或random()。 GUID 旨在作为以编程方式计算的值的虚拟对象。它将是客户的一些其他属性的散列值。所以必须用迁移来计算和更新。
如果您的数据库服务器是 SQL 服务器,您可以使用在数据库服务器
上生成 GUID 的内置newid()
函数
https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql
查询将是
Update dbo.Customers SET UniqueCode = newid()
如果是 SQLite 数据库,请使用 random()
函数。
我发现以下方法最适合我的情况。我建议将数据库和数据更改拆分为 2 个迁移,这样您就可以使用框架进行所有更改,并完全兼容上下兼容。
这里是我的方法的详细信息:
根据 Bradley Uffner 的建议,我循环遍历数据并逐行更新它。但是,在同一个迁移中执行此操作会引发错误:
The model backing the 'DbContext' context has changed since the database was created. Consider using Code First Migrations to update the database.
在迁移过程中使用 DbContext 会导致状态不一致。该模型已经处于迁移后状态,但数据库在表中仍具有迁移前状态。模型和数据库不匹配,导致出现上述错误。为了完成这项工作,我将不得不禁用模型检查。
参考:
在上面的线程中,我发现了将数据库更改与数据更改分开的建议。这正是我所做的。
我创建了一个迁移来更新数据库
Public Overrides Sub Up()
AddColumn("dbo.Customers", "WebCode", Function(c) c.String(unicode := false))
End Sub
Public Overrides Sub Down()
DropColumn("dbo.Customers", "WebCode")
End Sub
运行 Update-Database
命令。然后创建第二个迁移以进行数据更改。 Up
和 Down
方法在创建时将为空。这是我用来逐行更新数据的代码。
Public Overrides Sub Up()
Dim DbContext As New Data.DbContext
For Each customer In DbContext.Customers.Where(Function(x) String.IsNullOrEmpty(x.WebCode))
customer.WebCode = GetWebCode(customer)
Next
DbContext.SaveChanges()
End Sub
Public Overrides Sub Down()
Dim DbContext As New Data.DbContext
For Each customer In DbContext.Customers
customer.WebCode = Nothing
Next
MyDbContext.SaveChanges()
End Sub
有些人可能会争论在 Down 方法中使用简单的 SQL,例如
SQL("Update dbo.Customers SET WebCode = NULL")
效率更高。我已经尝试过了,但是在 JetEntityFrameworkProvider.JetMigrationSqlGenerator.GenerateSqlStatmentConcrete
遇到了一个我无法找到并修复的错误。它使 Visual Studio 崩溃。