C# 在C中尝试/捕获TransactionScope#
我在c代码中使用事务。在TransactionScope中,我记录了几乎所有的内容,以确保在测试中完成所有工作。但若在事务中发生了什么事情,它就会捕捉到我的日志类并没有写任何东西。在localhost中,我将TransactionScopeOption更改为“抑制”,因为数据库不在我的服务器中。当我调试一切正常时,我可以写入日志文件。但当我更改为“必需””时,如果它出现错误,它会像往常一样取消所有操作,但它也无法写入第一个日志。 我怎样才能解决这个问题 我的代码示例:C# 在C中尝试/捕获TransactionScope#,c#,asp.net,transactionscope,C#,Asp.net,Transactionscope,我在c代码中使用事务。在TransactionScope中,我记录了几乎所有的内容,以确保在测试中完成所有工作。但若在事务中发生了什么事情,它就会捕捉到我的日志类并没有写任何东西。在localhost中,我将TransactionScopeOption更改为“抑制”,因为数据库不在我的服务器中。当我调试一切正常时,我可以写入日志文件。但当我更改为“必需””时,如果它出现错误,它会像往常一样取消所有操作,但它也无法写入第一个日志。 我怎样才能解决这个问题 我的代码示例: TransactionOp
TransactionOptions tr = new TransactionOptions();
tr.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, tr, System.Transactions.EnterpriseServicesInteropOption.Automatic))//System.TimeSpan.MaxValue))
{
bool status = false;
// this log must be written anyway but it won't when it gives an error.
LogProcess log = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction begun.");
try
{
// process 1
// process 2
.
.
.
if(status)
{
LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction will complete soon.");
scope.Complete();
LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction completed.");
}
else
{
LogProcess log2 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction will dispose.");
scope.Dispose();
LogProcess log2 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction disposed.");
}
}
catch(Exception ex)
{
LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction exception. Error: " + ex.Message);
scope.Dispose();
}
}
首先,我发现您的代码示例的结构非常混乱。使用TransactionScope时,通常不会在调用scope.Complete()或scope.Dispose()后编写语句。此外,using语句为您处理作用域,因此如果您可以帮助的话,不应该显式调用scope.Dispose()。换句话说:尝试重构代码,使其看起来像这样:
private void PerformTransactionalOperation()
{
Log.Write("Starting operation.");
try
{
using (var scope = CreateTransactionScope())
{
if (PerformTransactionalOperationCore())
{
Log.Write("Committing...");
scope.Complete();
Log.Write("Committed");
}
else
{
Log.Write("Operation aborted.");
}
}
}
catch (Exception exception)
{
Log.Write("Operation failed: " + exception.Message);
throw;
}
}
private bool PerformTransactionalOperationCore()
{
// Perform operations and return status...
}
其次,事务作用域专门设计为仅在未引发异常时完成,因此可以通过让PerformTransactionalOperationCore引发特定异常而不是返回false来改进您的设计
然后讨论日志问题:确保您的日志框架不参与与您正在记录的操作相同的事务。您可以通过始终使用选项Suppress在TransactionScope中进行日志记录来实现这一点(即,当您首先登录到事务感知的资源(如数据库)时)。顺便问一下,为什么要通过实例化新的LogProcess实例来编写日志语句 首先,我发现您的代码示例的结构非常混乱。使用TransactionScope时,通常不会在调用scope.Complete()或scope.Dispose()后编写语句。此外,using语句为您处理作用域,因此如果您可以帮助的话,不应该显式调用scope.Dispose()。换句话说:尝试重构代码,使其看起来像这样:
private void PerformTransactionalOperation()
{
Log.Write("Starting operation.");
try
{
using (var scope = CreateTransactionScope())
{
if (PerformTransactionalOperationCore())
{
Log.Write("Committing...");
scope.Complete();
Log.Write("Committed");
}
else
{
Log.Write("Operation aborted.");
}
}
}
catch (Exception exception)
{
Log.Write("Operation failed: " + exception.Message);
throw;
}
}
private bool PerformTransactionalOperationCore()
{
// Perform operations and return status...
}
其次,事务作用域专门设计为仅在未引发异常时完成,因此可以通过让PerformTransactionalOperationCore引发特定异常而不是返回false来改进您的设计
然后讨论日志问题:确保您的日志框架不参与与您正在记录的操作相同的事务。您可以通过始终使用选项Suppress在TransactionScope中进行日志记录来实现这一点(即,当您首先登录到事务感知的资源(如数据库)时)。顺便问一下,为什么要通过实例化新的LogProcess实例来编写日志语句 日志是否也写入数据库?如果是,那就是你的问题。出现错误时,日志也将回滚。您需要将日志包装到另一个事务中,或者像文本文件一样记录到其他地方。@tucaz谢谢,您说得对。但是,即使在scope.Complete()之后一切正常,它也无法写入日志。这听起来像是日志记录的问题。什么是“逻辑过程”?我对它不熟悉。它在您的应用程序中的其他地方工作吗?出于性能原因,大多数日志提供程序都会“批量”将日志写入DB,如果您等到发出一定数量的日志请求,那么您将看到它们一起出现。此外,我还担心using语句中的手动作用域.Dispose()。您不需要它,因为它一离开“使用”范围就会被处理。日志是否也写入数据库?如果是,那就是你的问题。出现错误时,日志也将回滚。您需要将日志包装到另一个事务中,或者像文本文件一样记录到其他地方。@tucaz谢谢,您说得对。但是,即使在scope.Complete()之后一切正常,它也无法写入日志。这听起来像是日志记录的问题。什么是“逻辑过程”?我对它不熟悉。它在您的应用程序中的其他地方工作吗?出于性能原因,大多数日志提供程序都会“批量”将日志写入DB,如果您等到发出一定数量的日志请求,那么您将看到它们一起出现。此外,我还担心using语句中的手动作用域.Dispose()。你不需要它,因为它一离开“使用”范围就会被处理掉。我要试试。非常感谢。我的日志类通常非常广泛。我的客户几乎什么都想看。这只是测试的一个例子。我理解如果客户要求,您需要放入大量日志语句,我只是好奇您为什么选择这样实现它:每次需要记录一些东西时实例化一个新对象不是很传统(假设LogProcess构造函数执行实际写入)。我要试试。谢谢。我的日志类通常很宽。我的客户希望看到几乎所有的东西。那只是一个测试的例子。我理解你的要求,如果你的客户要求,你需要放很多日志语句。我只是好奇你为什么选择这样的方式来实现它:instanti不是很传统每次需要记录某些内容时,都会使用一个新对象(假设LogProcess构造函数执行实际写入)。