Entity Framework 6 / SQL Server 触发器 - 出现错误

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

我有一个 EF6 解决方案,我想在表上添加触发器以记录对新表的更改。这是由于我们正在对外部数据库进行集成。基本上,他们想要一份对表进行的更改日志以用于同步目的。

当我通过 SSMS(Azure SQL DB)执行时,触发器工作完美,但是当我通过 Web 应用程序测试时,出现以下错误:

(0x80131904): 如果 DML 语句包含 OUTPUT 子句而不包含 INTO 子句,则该语句的目标表“DestinationTable”不能有任何启用的触发器。

基本上,我似乎无法将触发器分配给使用实体框架的表。

有人对如何实现这项工作有想法吗?

提前致谢

c# sql-server entity-framework azure-sql-database
5个回答
16
投票

使用 EF Core 7.X 遇到相同的错误

我在表上有一个触发器,插入时返回错误。

The target table 'MyTable' of the DML statement cannot have any enabled 
triggers if the statement contains an OUTPUT clause without INTO clause

如果我没有逻辑地破坏了触发器,我仍然收到错误。禁用触发器解决了该错误。但是,如果我执行手动插入,SSMS 不会返回任何错误。

我的解决方案,(让 DBContext 实体对象知道触发器在表上)。

将 Fluent API 更新为...

builder.Entity<MyTable>(entry =>
    {
       entry.ToTable("MyTable", tb => tb.HasTrigger("MyTable_Insert"));
    });

更多信息可以在 与此主题相关的 Microsoft 网站 EF Core 7.0 (EF7) 中的重大更改


5
投票

我的问题是类似的 - 也关于

EF Core 7.X
中的重大更改,但我遵循了另一种路线,也出现在文档中,因为我的所有表都有触发器...

Microsoft 文档中所述,在“缓解”部分中,以下内容应该有所帮助:

如果您的大多数或所有表都有触发器,您可以通过以下方式选择不对所有模型的表使用更新、高效的技术 使用以下模型构建约定:

public class BlankTriggerAddingConvention : IModelFinalizingConvention
{
    public virtual void ProcessModelFinalizing(
        IConventionModelBuilder modelBuilder,
        IConventionContext<IConventionModelBuilder> context)
    {
        foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
        {
            var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table);
            if (table != null
                && entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(table.Value) == null))
            {
                entityType.Builder.HasTrigger(table.Value.Name + "_Trigger");
            }

            foreach (var fragment in entityType.GetMappingFragments(StoreObjectType.Table))
            {
                if (entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(fragment.StoreObject) == null))
                {
                    entityType.Builder.HasTrigger(fragment.StoreObject.Name + "_Trigger");
                }
            }
        }
    }
}

通过覆盖ConfigureConventions在DbContext上使用约定:

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Add(_ => new BlankTriggerAddingConvention());
}

2
投票

这是一个模糊的边缘情况,但我发现自己在这里,因为我使用 Microsoft.EntityFrameworkCore.SqlServer 7.0.0-preview 看到此错误。

当我恢复到 6.0.8 时,该错误就消失了。

我适合针对预览版进行开发。


1
投票

我发现了这个问题,它与我们正在使用的名为 ZEntity.BulkOperations.Extension 的扩展包有关。 David Browne 的评论让我记录了错误,并且内部异常指向 ZEntity BulkInsert 作为错误。然后我发现了这个链接 https://github.com/zzzprojects/EntityFramework-Extensions/issues/334 ,它指出这个包确实处理触发器。我所要做的就是使用数据库和包停止并重新启动服务,以便 ZEntity 发现新添加的触发器。

TLDR;我只需停止并启动服务即可使 ZEntity 包知道添加的触发器。

感谢所有回答的人!


0
投票

对于那些现在针对 Entity Framework Core 8 的用户,他们现在已经实现了逐个表使用或不使用“OUTPUT”子句的功能。

来自 Microsoft 文档

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlOutputClause(false));
}
© www.soinside.com 2019 - 2024. All rights reserved.