我们的许多DAL代码都使用TransactionScope进行交易.这很好用但是当我在SQLCLR程序中使用这个DAL代码时会出现问题.交易升级到MSDTC我不想要的.
问题可以轻松复制:
CLR实施
[SqlProcedure]
public static void ClrWithScope(string cmdText)
{
/* escalates to MSDTC when a transaction is already open */
using ( var scope = new TransactionScope())
{
using (var connection = new SqlConnection("context connection=true;"))
{
connection.Open();
using (var cmd = new SqlCommand(cmdText, connection))
{
SqlContext.Pipe.ExecuteAndSend(cmd);
}
}
scope.Complete();
}
}
[SqlProcedure]
public static void ClrWithTrans(string cmdText)
{
/* works as expected (without MSDTC escalation ) */
using (var connection = new SqlConnection("context connection=true;"))
{
connection.Open();
using (var tx …Run Code Online (Sandbox Code Playgroud)我们编写了一个C#3.5客户端,使用ODP.NET与Oracle数据库(11g)进行通信.
此应用程序具有批处理过程,其中执行长时间运行的任务,在TransactionScope中对数据库进行各种调用.
在我们的开发环境中一切顺利,但在我们的一个客户(拥有大量数据)的UAT环境中,出现两个交替(有时是一个,有时是另一个......)错误:
我们目前使用一天的超时时间进行交易(用于测试目的).
在UAT环境中运行所述进程导致在大约一段时间后停止.10分钟,上面有一个例外,所以没有办法接近超时值.
这是第二个错误的堆栈跟踪片段:
at System.Transactions.TransactionStatePromotedAborted.CreateAbortingClone(InternalTransaction tx)
at System.Transactions.DependentTransaction..ctor(IsolationLevel isoLevel, InternalTransaction internalTransaction, Boolean blocking)
at System.Transactions.Transaction.DependentClone(DependentCloneOption cloneOption)
at System.Transactions.TransactionScope.SetCurrent(Transaction newCurrent)
at System.Transactions.TransactionScope.PushScope()
at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption)
at System.Transactions.TransactionScope..ctor()
at Application.Domain.DataAccess.Oracle.EntityDaoBase`2.SaveItem(TEntity item, EntityReference`1 user)
Run Code Online (Sandbox Code Playgroud)
该过程尝试将项目保存到事务范围内的数据库,但堆栈跟踪显示构造函数被命中为TransactionScope类,这意味着它创建了一个新的TransactionScope.
我到目前为止对吗?
因为我不太了解TransactionScope的内部工作原理,但是当你在范围内调用方法时,它会创建一个新的事务(假设继承自环境事务).
可能是因为我是对的,这个新事务没有继承正确的超时(但是默认的超时),所以嵌套事务会导致这个超时异常?
如果没有,任何想法可能是什么?另外,在环境事务中调用的方法中没有定义嵌套事务.
任何帮助将不胜感激!
编辑1:
该功能的简化代码片段:
public void SomeLengthyBatchProcess()
{
using (var transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))
{
foreach (var item in Items)
{
SaveItemToDB(item);
}
transaction.Complete();
}
}
public void SaveItemToDB(object item)
{ …Run Code Online (Sandbox Code Playgroud) 我有两个存储库指向相同的SQL Server 2008 R2(10.50.2550.0)数据库。一个存储库基于Entity Framework,另一个使用常规的SqlConnection。我需要执行涉及这两者的操作,因此我使用了a TransactionScope来使它们保持在同一事务中:
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions() { IsolationLevel = IsolationLevel.RepeatableRead }))
{
_repoA.DoStuff();
_repoB.DoStuff();
}
Run Code Online (Sandbox Code Playgroud)
由于我在两者中都使用相同的连接字符串:
"Data Source=(local);Initial Catalog=mydb;User Id=myid;Password=mypass;Asynchronous Processing=true"
Run Code Online (Sandbox Code Playgroud)
我期望SQL Server 2008 R2可以使用多个连接而无需扩展。不幸的是,我得到一个例外的说法:
发生System.Data.SqlClient.SqlException Message = MSDTC在服务器'MyComputer'上不可用。Source = .Net SqlClient数据提供程序
ErrorCode = -2146232060类= 16 LineNumber = 1 Number = 8501
Procedure =“” Server =(local)State = 2 StackTrace:位于System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔值BreakConnection )
可能是什么问题呢?
干杯。
msdtc transactions transactionscope sql-server-2008-r2 entity-framework-4.3
我们使用3层建筑,其中包含SqlHelper - > DAL(数据访问层) - > BAL - > UI
DAL中的任何类都可以调用另一个DAL,任何BAL都可以调用另一个BAL或DAL.
例如.
class Customer_DAL { display_CusDal(); }
class Customer_BAL { display_CusBal(); }
class Product_DAL { display_ProDal(); }
class Product_BAL { display_ProBal(); }
display_CusDal()
{
//call display_ProDal()
//Do some work
}
Run Code Online (Sandbox Code Playgroud)
display_CusDal 函数应作为事务运行,实体意味着在此函数中进行的任何插入都应与事务对象相关联.
由于display_CusDal可以调用display_ProDal,这可能会也可能不会在另一个事务中的表中插入数据,所以我需要在事务中处理这些.
我应该使用什么方法.
[使用:C#3.5 + SQL Server 2005]
我在Business Layer中有一些代码,它们在TransactionScope中包含订单的创建及其详细信息:
DAL.DAL_OrdenDeCompra dalOrdenDeCompra = new GOA.DAL.DAL_OrdenDeCompra();
DAL.DAL_ItemDeUnaOrden dalItemDeUnaOrden = new GOA.DAL.DAL_ItemDeUnaOrden();
using (TransactionScope transaccion = new TransactionScope())
{
//Insertion of the order
orden.Id = dalOrdenDeCompra.InsertarOrdenDeCompra(orden.NumeroOrden, orden.PuntoDeEntregaParaLaOrden.Id, (int)orden.TipoDeCompra, orden.FechaOrden, orden.Observaciones);
foreach (ItemDeUnaOrden item in orden.Items)
{
//Insertion of each one of its items.
dalItemDeUnaOrden.InsertarItemDeUnaOrden(orden.Id, item.CodigoProductoAudifarma, item.CodigoProductoJanssen, item.CodigoEAN13, item.Descripcion, item.CantidadOriginal, item.ValorUnitario);
}
transaccion.Complete();
}
return true;
Run Code Online (Sandbox Code Playgroud)
以下是执行插入的DAL代码:
public int InsertarOrdenDeCompra(string pNumeroOrden, int pPuntoEntregaId, int pTipoDeCompra, DateTime pFechaOrden, string pObservaciones)
{
try
{
DataTable dataTable = new …Run Code Online (Sandbox Code Playgroud)