【问题标题】:Entity Framework "The current transaction cannot be committed and cannot support operations that write to the log file."实体框架“当前事务无法提交,并且无法支持写入日志文件的操作。”
【发布时间】:2014-06-16 09:40:07
【问题描述】:

我正在开发的一款软件用于将数据从 CSV 文件上传到数据库中。与数据库的交互使用的是 EF6。要提交数据,有一个名为“InsertRow”的存储过程,它接受接口ID(字符串)、数据行(字符串)、分隔符(字符串),并具有输出参数:错误代码(int)和错误消息( 0)。 SP 定义如下所示:

CREATE PROCEDURE [dbo].[InsertRow]
(
  @InterfaceID NVARCHAR(MAX) ,
  @Row NVARCHAR(MAX) ,
  @Delimiter NVARCHAR(MAX) ,
  @ErrorCode INT OUTPUT ,
  @ErrorMessage NVARCHAR(MAX) OUTPUT    
)

它是这样从实体调用的:

public virtual int InsertRow(string interfaceID, string row, string delimiter)
    {
        var errorCode = new ObjectParameter("ErrorCode", typeof(int));

        var errorMessage = new ObjectParameter("ErrorMessage", typeof(string));

        var interfaceIDParameter = interfaceID != null ?
            new ObjectParameter("InterfaceID", interfaceID) :
            new ObjectParameter("InterfaceID", typeof(string));

        var rowParameter = row != null ?
            new ObjectParameter("Row", row) :
            new ObjectParameter("Row", typeof(string));

        var delimiterParameter = delimiter != null ?
            new ObjectParameter("Delimiter", delimiter) :
            new ObjectParameter("Delimiter", typeof(string));

        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("InsertRow", interfaceIDParameter, rowParameter, delimiterParameter, errorCode, errorMessage);
    }

仅当临时表已创建(在调用此表之前完成)时,该过程才有效,因此 EF 上下文需要在提交所有行时保持打开状态。这不是问题,正在管理中。该过程执行一些验证,显然还有一些从字符串到正确数据类型的转换。输出参数 Error Code 和 Error Message 填充了错误信息以供应用程序处理。该过程以执行此操作的 catch 结束:

    BEGIN CATCH 
    SET @ErrorCode = ERROR_NUMBER()  
    SET @ErrorMessage = ERROR_MESSAGE()
    INSERT INTO ErrorLog values (GetDate(),@InterfaceID, @Row, @Deliminator, ERROR_NUMBER(), ERROR_MESSAGE())
END CATCH;

大多数时候,这是可行的。但是,在某些情况下,不会设置错误代码和错误消息,而是会引发 EntityCommandExecutionException 和以下内部异常消息:

“当前事务无法提交,不支持写入日志文件的操作。回滚事务。”

我很难理解为什么抛出的一些错误会在这里捕获并正确处理,而另一些则会失败。例如,当提交字符串“日期文本”作为应输入到日期时间字段的行的一部分时。这应该被捕获和报告,但是我得到了一般的异常。

还值得注意的是,我也从 Catch 块中删除了插入语句。然后异常的消息变为

“在批处理结束时检测到不可提交的事务。事务回滚。”

以前有人见过这个问题吗?我们在这里缺少什么可以帮助我们解决它?什么会导致交易无法提交?我们需要有效地捕获这些消息,以便向用户报告他们文件的问题。

【问题讨论】:

    标签: c# sql sql-server entity-framework transactions


    【解决方案1】:

    有时事务确实是不可提交的,例如,如果您尝试插入一行,而目标表上有触发器,则触发器失败。

    您应该始终检查 BEGIN CATCH 块中的 XACT_STATE() 以查看您是否可以提交事务。请参阅the docs 了解更多信息。

    如果您想可靠地记录故障,我建议您使用 SQL 审计功能,并在 BEGIN CATCH 块中使用 EXEC sp_audit_write 过程。再次,请参阅the docs 了解更多信息。或者,如果您无法使用审核,RAISERROR ... WITH LOG 会将消息记录到 SQL Server 错误日志中。

    【讨论】:

      【解决方案2】:

      实体框架抛出了这个异常。

      TRIGGERS 是罪魁祸首。我修改了一些模型,添加了迁移,更新了数据库......但不是触发器

      这个异常是在处理过程中的某个时刻抛出的。

      修复触发器解决了问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多