簡體   English   中英

盡管檢查了應用的遷移,EF Core 冪等遷移腳本仍失敗

[英]EF Core idempotent migration script fails despite check on applied migration

我正在使用 EF Core (3.1.15)。 在之前的遷移(也在 3.1.15 中創建)中,引用了稍后刪除的列。 冪等腳本會檢查是否在數據庫上執行了遷移(確實如此,並且引用仍顯示在__EFMigrationsHistory表中)。 但是,由於列不存在,檢查沒有預期的結果和腳本。

:為什么不存在的列會導致 SQL 腳本的執行跳閘?

腳本是用

dotnet-ef migrations script -i -o migrations.sql

失敗的自動化腳本的相關部分,其中ReferenceToLedgerId是在以后遷移中刪除的列:

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
    UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;

錯誤:

Msg 207, Level 16, State 1, Line 3
無效的列名“ReferenceToLedgerId”

運行以下 SQL 查詢時,結果按預期返回:

SELECT * 
FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger'
遷移 ID 產品版本
20210612052003_CLedger 3.1.15

數據庫是 Azure SQL 數據庫。 腳本不會在本地 SQL 開發數據庫上失敗。 從那時起已經應用了十幾個遷移,只是現在腳本失敗了。

下面是創建特定腳本的調用:

migrationBuilder.Sql("UPDATE LedgerTable set LedgerId = ReferenceToLedgerId", true);

我試圖將表名和列名放在方括號中,但這沒有區別(例如[ReferenceToLedgerId] 。使用SQLCMD時,該腳本在 Azure DevOps 版本中失敗,在使用 Azure Data Studio 時也失敗,兩者都訪問 Azure SQL 數據庫.


額外檢查

我更改了腳本以進行快速檢查:

PRINT '#Before IF'
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
    PRINT '#Within IF'
    --UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;

PRINT '#After IF'

我得到以下結果:

從第 1 行開始執行查詢 #Before IF #After IF 總執行時間:00:00:00.010

如果我取消注釋UPDATE語句,它將再次失敗。 所以我只能得出結論,代碼路徑按預期工作,但服務器仍會檢查該列是否存在。 我對 SQL 不熟悉,不明白為什么會這樣,或者為什么它只在這一行失敗,而列本身在 SQL 腳本的其他行中被引用而沒有失敗。

該批處理將在每個版本的 SQL Server 上失敗。 例如

use tempdb
go
create table __EFMigrationsHistory(MigrationId nvarchar(200))
create table LedgerTable(LedgerId int)
go
insert into __EFMigrationsHistory(MigrationId) values (N'20210612052003_CLedger')
go
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
    UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;

失敗

Msg 207, Level 16, State 1, Line 8
Invalid column name 'ReferenceToLedgerId'.

因為批處理無法解析和編譯。 在 TSQL 批處理中引用不存在的表或列是不合法的。

您可以使用動態 SQL 解決此問題,這樣除非正在應用遷移,否則不會解析和編譯引用不存在的列的批處理。

migrationBuilder.Sql("exec('UPDATE LedgerTable set LedgerId = ReferenceToLedgerId')", true);

這是記錄在這里:

小費

當語句必須是 SQL 批處理中的第一個或唯一一個時,請使用 EXEC 函數。 可能還需要解決冪等遷移腳本中的解析器錯誤,當表中當前不存在引用的列時,這些錯誤可能會發生。

https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/operations

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM