3

我正在寻找一种适当的方法来扩展现有数据库,基于实体框架 6 代码优先实现,并为表中每个现有行的新字段添加唯一值。

到目前为止,我已经创建了一个添加新字段的迁移。

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 旨在成为以编程方式计算的值的虚拟对象。它将是客户其他一些属性的哈希值。所以它必须通过迁移来计算和更新。

4

2 回答 2

2

我发现以下方法最适合我的情况。我建议将数据库和数据更改拆分为 2 次迁移,这样您就可以使用框架进行所有更改并完全上下兼容。

这是我的方法的详细信息:

按照 Bradley Uffner 的建议,我遍历数据并逐行更新它。但是,在同一个迁移中执行此操作会引发错误:

自数据库创建以来,支持“DbContext”上下文的模型已更改。考虑使用 Code First 迁移来更新数据库。

在迁移过程中使用 DbContext 会导致状态不一致。模型已经处于迁移后状态,但数据库在表中仍然具有迁移前状态。模型和数据库不匹配,导致上述错误。为了完成这项工作,我必须禁用模型检查。

参考:迁移Up方法中的更改数据-实体框架

在上面的线程中,我发现了将数据库更改与数据更改分开的建议。这正是我所做的。

我创建了一个迁移来更新数据库

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

于 2017-08-11T09:44:31.003 回答
1

如果您的数据库服务器是 SQL Server,您可以使用newid()在数据库服务器上生成 GUID 的内置函数

https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql

查询将是

Update dbo.Customers SET UniqueCode = newid()

如果是 SQLite 数据库,请使用该random()函数。

于 2017-08-10T13:39:39.463 回答