我正在使用的一个软件用于将CSV文件中的数据上传到数据库中。与数据库的交互使用EF6。要提交数据,有一个名为“InsertRow”的存储过程,它接受InterfaceID(字符串),数据行(字符串),分隔符(字符串),并具有输出参数:错误代码(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上下文需要保持打开状态。这不是问题,正在管理中。该过程执行一些验证,显然是从字符串到正确的数据类型的一些转换。输出参数错误代码和错误消息将填充错误信息以供应用程序处理。程序以一个捕获符号结束:
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,并显示以下内部异常消息:
“当前事务无法提交,也无法支持写入日志文件的操作。回滚事务。”
我很难理解为什么抛出的某些错误会被捕到并正确处理,而其他错误则会失败。例如,提交字符串“date text”作为应该输入DateTime字段的Row的一部分。这应该被捕获并报告,但我得到了一般异常。
值得注意的是,我也从Catch块中删除了insert语句。然后该异常消息将更改为
“在批处理结束时检测到无法提交的事务。事务将被回滚。”
以前有人见过这个问题吗?我们在这里缺少什么可以帮助我们解决它?什么可能导致交易无法承受?我们需要有效地捕获这些消息,以便我们向用户报告其文件的问题。
答案 0 :(得分:0)
有时事务确实是不可承认的,例如,如果您尝试INSERT一行,并且目标表上有触发器,并且触发器失败。
您应该始终检查XACT_STATE()
块中的BEGIN CATCH
,看看您是否可以提交交易。有关详细信息,请参阅the docs。
如果您想要可靠地记录故障,我建议使用SQL Audit功能,以及EXEC sp_audit_write
块中的BEGIN CATCH
过程。再次,请参阅the docs了解更多信息。或者,如果您无法使用审计,则RAISERROR ... WITH LOG
会将消息记录到SQL Server错误日志。
答案 1 :(得分:-1)
实体框架引发了此异常。
肇事者是罪魁祸首。我已经修改了一些模型,添加了迁移,更新了数据库……但是没有触发
此异常在处理过程中的某个时刻抛出。
修复TRIGGERS解决了问题。