升级到.NET 8.0后,我收到EntityFrameworkCore.DbUpdateException:“无法保存更改,因为目标表有数据库触发器”

问题描述 投票:0回答:1

我将 ASP.NET Core 6 Web API 升级到 .NET 8.0。

Signin
页面,我有以下代码:

public async Task<IActionResult> LoginAttempt([Bind("Email","Password","PingIdPin","SelectDeviceMessage","SelectDevice","CollectPinMessage","CollectPin","MultipleDevices","MultipleDevicesYesNo","ChallengeId","UserPrompt","LoginFailed")] LoginModel loginModel)
{
    // more snippets of the code
    Microsoft.AspNetCore.Identity.SignInResult result = new();

    try
    {
        result = await _signInManager.PasswordSignInAsync(user, password, false, false);
    }
    catch (Exception ex)
    {
        string ss = ex.Message;
        _logger.LogInformation(-999000001, "{0} ... result = await _signInManager.PasswordSignInAsync(user, password, false, false); [{1}]", nameof(Login), ex.Message);
    }
}

我得到这个例外:

EntityFrameworkCore.DbUpdateException:Microsoft.EntityFrameworkCore.DbUpdateException:'无法保存更改,因为目标表具有数据库触发器。请相应地配置您的表,请参阅 https://aka.ms/efcore-docs-sqlserver-save-changes-and-output-clause 了解更多信息。'

SqlException:如果该语句包含不带 INTO 子句的 OUTPUT 子句,则 DML 语句的目标表“AspNetUsers”不能有任何启用的触发器。

我将 Entity Framework Core 的所有 Nuget 包升级到 8.0.8。

请参阅 NugetPackages for 8.0

的屏幕截图

使用.NET 6.0,它可以无缝运行。不确定升级到 .NET 8.0 时缺少什么。

请让我知道如何解决这个问题。

asp.net-core entity-framework-core asp.net-core-webapi .net-8.0
1个回答
0
投票

这是新版本 EF Core 中的设计初衷。请参阅文档页面 带有触发器或某些计算列的 SQL Server 表现在需要特殊的 EF Core 配置,错误消息本身会将您链接到:

旧行为

以前版本的 SQL Server 提供程序通过一种效率较低的技术保存更改,但该技术始终有效。

新行为

默认情况下,EF Core 现在通过显着更高效的技术保存更改; 不幸的是,如果目标表具有数据库触发器或某些类型的计算列,则 SQL Server 不支持此技术。有关更多详细信息,请参阅 SQL Server 文档。

[...]

缓解措施

从 EF Core 8.0 开始,可以显式配置是否使用“OUTPUT”子句。例如:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<Blog>()
       .ToTable(tb => tb.UseSqlOutputClause(false));
}

在 EF7 或更高版本中,如果目标表有触发器,那么您可以让 EF Core 知道这一点,EF 将恢复到以前的效率较低的技术。这可以通过配置相应的实体类型来完成,如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<Blog>()
       .ToTable(tb => tb.HasTrigger("SomeTrigger"));
}

请注意,执行此操作实际上并不会让 EF Core 以任何方式创建或管理触发器 - 它当前仅通知 EF Core 表上存在触发器。因此,可以使用任何触发器名称。 指定触发器可用于恢复旧行为,即使表中实际上没有触发器。

(粗体强调我的)

在该页面上进一步阅读,查看一个代码示例,用于选择退出all模型表的新技术,而不是依赖于每个表的缓解措施。

相关:SQL Server:检索数据库生成的值时优化 SQL Server OUTPUT 子句的使用#27372 - 有关该问题的早期 GitHub 错误报告
相关:SaveChanges、数据库触发器和不支持的计算列 - Microsoft 文档页面,涵盖 SQL Server 的各种注释

© www.soinside.com 2019 - 2024. All rights reserved.