如何让Entity Framework 7在更新操作中不使用OUTPUT子句?
解决EF7更新时因OUTPUT子句与触发器冲突的问题
问题核心是EF7默认生成带OUTPUT 1的UPDATE语句,而SQL Server不允许带启用触发器的表使用无INTO子句的OUTPUT。下面是几种可行的解决办法:
1. 直接使用原生SQL执行更新
完全跳过EF的自动SQL生成,手动编写不含OUTPUT的UPDATE语句,通过ExecuteSqlAsync执行:
var updateSql = @"UPDATE [ObrazacZahtjevZaIzvanrednuPozajmicu] SET [OdbijenOdobren] = @p0 WHERE [ObrazacZahtjevZaIzvanrednuPozajmicuId] = @p1 AND [Zakljucan] = @p2;"; await context.Database.ExecuteSqlAsync( updateSql, new SqlParameter("@p0", true), new SqlParameter("@p1", 21858), new SqlParameter("@p2", false) );
这种方式最直接,完全控制SQL结构,避免触发器冲突。
2. 使用EF拦截器修改生成的SQL
如果想保留EF的LINQ查询语法,可以通过拦截器替换掉生成的OUTPUT子句,改用@@ROWCOUNT返回受影响行数:
第一步:定义拦截器
public class RemoveOutputClauseInterceptor : DbCommandInterceptor { public override InterceptionResult<DbDataReader> ReaderExecuting( DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result) { // 定位EF生成的带OUTPUT的更新语句 if (command.CommandText.Contains("OUTPUT 1") && command.CommandText.StartsWith("SET IMPLICIT_TRANSACTIONS OFF;")) { // 替换OUTPUT子句,改用SELECT @@ROWCOUNT获取行数 var modifiedSql = command.CommandText.Replace( "OUTPUT 1", "; SELECT @@ROWCOUNT;" ); command.CommandText = modifiedSql; } return base.ReaderExecuting(command, eventData, result); } }
第二步:注册拦截器到DbContext
在OnConfiguring方法中添加拦截器:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer("你的数据库连接字符串") .AddInterceptors(new RemoveOutputClauseInterceptor()); }
之后使用EF的ExecuteUpdateAsync时,生成的SQL会自动替换掉OUTPUT部分,避免触发器报错。
3. 临时禁用触发器(不推荐)
如果上述方法都无法使用,可以临时禁用目标表的触发器,更新完成后再启用,但这会带来数据一致性风险,仅作为最后备选:
// 禁用触发器 await context.Database.ExecuteSqlAsync(@"DISABLE TRIGGER ALL ON [ObrazacZahtjevZaIzvanrednuPozajmicu];"); // 执行EF更新 await context.ObrazacZahtjevZaIzvanrednuPozajmicu .Where(x => x.ObrazacZahtjevZaIzvanrednuPozajmicuId == 21858 && x.Zakljucan == false) .ExecuteUpdateAsync(setters => setters.SetProperty(x => x.OdbijenOdobren, true)); // 重新启用触发器 await context.Database.ExecuteSqlAsync(@"ENABLE TRIGGER ALL ON [ObrazacZahtjevZaIzvanrednuPozajmicu];");
内容的提问来源于stack exchange,提问作者Hrvoje
相关产品推荐
相关产品推荐

