如何使用 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 命令。然后创建第二个迁移以进行数据更改。 UpDown 方法在创建时将为空。这是我用来逐行更新数据的代码。

    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 崩溃。