首页 > 解决方案 > EF6 Update-Database 正在尝试创建将复制现有计算列的列

问题描述

我在 SQL 数据库中有一些计算列,这给 EF6 带来了很多麻烦。我正在使用这种技术

出于某种原因,PM 命令Update-Database坚持尝试将列添加到已经作为计算列存在的表中。

我只是通过临时启用自动迁移才发现这一点的。禁用自动迁移后,我得到了著名的“无法更新数据库以匹配当前模型,因为有待处理的更改并且禁用了自动迁移”。

以下是相关的摘录 SQL 输出Update-Database -Verbose

Applying explicit migration: 201805012255477_001.
CREATE TABLE [dbo].[LogEntries] (
    [Id] [int] NOT NULL IDENTITY,
    [ReceiveTime] [datetime] NOT NULL DEFAULT '1753-01-01T00:00:00.000',
    [SendTime] [datetime] NOT NULL DEFAULT '1753-01-01T00:00:00.000',
    [LogTime] [datetime] NOT NULL DEFAULT '1753-01-01T00:00:00.000',
    [Scale] [real] NOT NULL DEFAULT 0,
    [Co] [real] NOT NULL DEFAULT 0,
    [O2] [real] NOT NULL DEFAULT 0,
    CONSTRAINT [PK_dbo.LogEntries] PRIMARY KEY ([Id])
)

...

ALTER TABLE [LogEntries] ADD [CorrectionFactor] AS (13.9 / (20.9 - [O2])) PERSISTED

...

Applying automatic migration: 201901160207184_AutomaticMigration.
ALTER TABLE [dbo].[LogEntries] ADD [CorrectionFactor] [real] NOT NULL DEFAULT 0
System.Data.SqlClient.SqlException (0x80131904): Column names in each table must be unique. Column name 'CorrectionFactor' in table 'dbo.LogEntries' is specified more than once.

(请注意,我没有创建名为AutomaticMigration. 的迁移。EF6 似乎是自己做的。)

值得一提的是,数据库和表都创建成功。直到我上次迁移运行后才会出现此问题。

预期结果

Update-Database命令应该没有错误地完成

实际结果

Update-Database命令尝试创建重复列,导致数据库错误

我尝试过的事情

  1. 使用数据注释而不是 Fluent API,以防 EF6 中出现模糊的错误
  2. 彻底删除数据库,从头开始
  3. 仔细检查所有迁移(和支持代码)的准确性
  4. 从项目中排除所有迁移并生成一个新迁移
  5. 添加.Ignore()API;但是,那和.HasDatabaseGeneratedOption()API 是互斥的

.HasDatabaseGeneratedOption()API似乎没有效果。还可以做些什么来指示 EF6 不尝试创建该列?

这是我的代码:

语境

Namespace Db
  Public Class Context
    Inherits DbContext

    Public Sub New()
      MyBase.New(Utils.DbConnectionString)
    End Sub

    Private Sub New(Connection As DbConnection)
      MyBase.New(Connection, True)

      Database.SetInitializer(New CreateDatabaseIfNotExists(Of Context))
      Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of Context, Migrations.Configuration))

      Me.Database.Initialize(False)
    End Sub

    Public Shared Function Create() As Context
      Return New Context(DbConnection)
    End Function

    Private Shared ReadOnly Property DbConnection As SqlConnection
      Get
        Return New SqlConnection(Utils.DbConnectionString)
      End Get
    End Property

    Protected Overrides Sub OnModelCreating(Builder As DbModelBuilder)
      Builder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly)
      MyBase.OnModelCreating(Builder)
    End Sub

    Public Property LogEntries As DbSet(Of LogEntry)
  End Class
End Namespace

实体

Namespace Db
  Public Class LogEntry
    Public Property Id As Integer
    Public Property ReceiveTime As Date
    Public Property SendTime As Date
    Public Property LogTime As Date
    Public Property Scale As Single
    Public Property Scc As Single
    Public Property Co As Single
    Public Property O2 As Single

#Region " Computed Columns "

    Public Property CorrectionFactor As Single
      Get
        Return 13.9 / (20.9 - Me.O2)
      End Get
      Private Set(Value As Single) : End Set
    End Property

    Public Property MinutesOffline As Single
      Get
        Return IIf(Me.Scale < 1, 1, 0)
      End Get
      Private Set(Value As Single) : End Set
    End Property

    Public Property OffsetTime As Date
      Get
        Return Me.LogTime.AddHours(-7)
      End Get
      Private Set(Value As Date) : End Set
    End Property

    Public Property Co7Online As Single
      Get
        Return IIf(Me.Scale > 1, Me.Co7, 0)
      End Get
      Private Set(Value As Single) : End Set
    End Property

    Public Property Shift As Short
      Get
        Return IIf(Me.OffsetTime.Hour < 12, 1, 2)
      End Get
      Private Set(Value As Short) : End Set
    End Property

    Public Property Co7 As Single
      Get
        Return Me.Co * Me.CorrectionFactor
      End Get
      Private Set(Value As Single) : End Set
    End Property

#End Region

  End Class
End Namespace

配置

Namespace Configurations
  Public Class LogEntry
    Inherits EntityTypeConfiguration(Of Db.LogEntry)

    Public Sub New()
      Me.Property(Function(Entry) Entry.ReceiveTime).IsRequired()
      Me.Property(Function(Entry) Entry.SendTime).IsRequired()
      Me.Property(Function(Entry) Entry.LogTime).IsRequired()
      Me.Property(Function(Entry) Entry.Scale).IsRequired()
      Me.Property(Function(Entry) Entry.Scc).IsRequired()
      Me.Property(Function(Entry) Entry.Co).IsRequired()
      Me.Property(Function(Entry) Entry.O2).IsRequired()

      Me.HasIndex(Function(Entry) Entry.ReceiveTime).HasName("IX_LogEntries_ReceiveTime")
      Me.HasIndex(Function(Entry) Entry.SendTime).HasName("IX_LogEntries_SendTime")
      Me.HasIndex(Function(Entry) Entry.LogTime).HasName("IX_LogEntries_LogTime")
      Me.HasIndex(Function(Entry) Entry.Scale).HasName("IX_LogEntries_Scale")
      Me.HasIndex(Function(Entry) Entry.Scc).HasName("IX_LogEntries_Scc")
      Me.HasIndex(Function(Entry) Entry.Co).HasName("IX_LogEntries_Co")
      Me.HasIndex(Function(Entry) Entry.O2).HasName("IX_LogEntries_O2")

      Me.Property(Function(Entry) Entry.CorrectionFactor).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
      Me.Property(Function(Entry) Entry.MinutesOffline).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
      Me.Property(Function(Entry) Entry.OffsetTime).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
      Me.Property(Function(Entry) Entry.Co7Online).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
      Me.Property(Function(Entry) Entry.Shift).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
      Me.Property(Function(Entry) Entry.Co7).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
    End Sub
  End Class
End Namespace

标签: sql-serverentity-frameworkef-code-first

解决方案


推荐阅读