This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
It seems there is a problem in the private method
Mindscape.LightSpeed.UnitOfWork.SystemTransactionCompletedEvent,
which is assigned to the Transaction.Current.TransactionCompleted as the event handler in the overriden
UnitOfWork.SaveChanges(bool reset)
method.
Here is fragment of the event handler's code:
private void SystemTransactionCompletedEvent(..., TransactionEventArgs e)
{
e.Transaction.TransactionCompleted -= SystemTransactionCompletedEvent;
...... // here is the "diposed transaction" exception thrown
}
e.Transaction is not null, but disposed. So accessing any member of this disposed instance leads to throwing corresponding exception.
This situation arises when running this fragment of code:
Guid id = Guid.Empty;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
...... // real code removed
// context.UnitOfWorkScope.Current is UnitOfWork instance
context.UnitOfWorkScope.Current.Add(newData);
context.UnitOfWorkScope.Current.SaveChanges(); // *** this line leads to throwing some exception, because of foreign key constraints ***
....... //real code removed
id = newData.Id;
scope.Complete();
}// *** at this line current thread breaks when "accessing disposed transaction" exception is thrown - seeing that in the thread and call stack windows.
Resume: One thread calls UnitOfWork.SaveChanges, UnitOfWork.SaveChanges assigns the event hanlder method for the TransactionCompleted. When peforming save, exception is thrown, the created TransactionScope instance is disposed (the last line in the using(....){...} block), then asynchronously, in second thread
SystemTransactionCompletedEvent event handler is called, but the transaction object is already disposed.
We think the problem is the code of the SystemTransactionCompletedEvent method, since it supposes, that transaction is not disposed.
Are we right?
Can we avoid the "diposed transaction" exception in some way, e.g. using some synchronization objects? Do we (for you) obviously ignore some aspect of Lightspeed?
Thanks a lot in advance for your reactions.
|
|
|
It seems there is a problem in the private method
which is assigned to the Transaction.Current.TransactionCompleted as the event handler in the overriden
method. Here is fragment of the event handler's code: private void SystemTransactionCompletedEvent(..., TransactionEventArgs e) e.Transaction is not null, but disposed. So accessing any member of this disposed instance leads to throwing corresponding exception.
// context.UnitOfWorkScope.Current is UnitOfWork instance context.UnitOfWorkScope.Current.Add(newData);
Resume: One thread calls UnitOfWork.SaveChanges, UnitOfWork.SaveChanges assigns the event hanlder method for the TransactionCompleted. When peforming save, exception is thrown, the created TransactionScope instance is disposed (the last line in the using(....){...} block), then asynchronously, in second thread SystemTransactionCompletedEvent event handler is called, but the transaction object is already disposed.
Are we right? Thanks a lot in advance for your reactions. |
|
|
v System.Transactions.Transaction.get_TransactionInformation() v Mindscape.LightSpeed.UnitOfWork.SystemTransactionCompletedEvent(Object sender, TransactionEventArgs e) v C:\development\projects\wirmim\Program.v2.0\Lib\Mindscape.LightSpeed\Src\Framework\UnitOfWork.cs:řádek 514 v System.Transactions.TransactionCompletedEventHandler.Invoke(Object sender, TransactionEventArgs e) v System.Transactions.InternalTransaction.FireCompletion() v System.Transactions.TransactionStatePromotedAborted.EnterState(InternalTransaction tx) v System.Transactions.TransactionStateDelegatedAborting.ChangeStatePromotedAborted(InternalTransaction tx) v System.Transactions.DurableEnlistmentDelegated.Aborted(InternalEnlistment enlistment, Exception e) v System.Transactions.SinglePhaseEnlistment.Aborted() v System.Data.SqlClient.SqlDelegatedTransaction.Rollback(SinglePhaseEnlistment enlistment) v System.Transactions.TransactionStateDelegatedAborting.EnterState(InternalTransaction tx) v System.Transactions.TransactionStateDelegated.Rollback(InternalTransaction tx, Exception e) v System.Transactions.Transaction.Rollback() v System.Transactions.TransactionScope.InternalDispose() v System.Transactions.TransactionScope.Dispose() v BluePixel.Wirmim.Extensions.LightSpeedEntity.Add
![]() ![]() ![]() ![]() |
|
|
Hi, We are seeing the same behaviour when TransactionScope wraps a unitOfWork. Are suggested solutions/work arounds?
|
|
|
We have not been able to reproduce this. We expect .NET to call the TransactionCompleted event before it disposes the transaction (and this is what appears to happen in our tests) -- otherwise the TransactionEventArgs would be useless. Could you provide us with a simple console project or NUnit test that reproduces this behaviour? Thanks! |
|
|
Hi, We have created the sample console project which runs in windows 7 but not windows xp. On windows xp, it throws the error: Cannot access a disposed object. Stack trace: at System.Transactions.Transaction.get_TransactionInformation() Steps to reproduce 1) Extract the zip file 2) Restore the database file DB\LsTestDb.bak 3) Open solution with Visaul studio 2008 4) F5 and run console app |
|
|
Simple console test app attached in this post |
|
|
Thanks! Unfortunately, it looks like the zip file went awry -- could you re-post please? You can attach a file via the Options tab. |
|
|
You're too fast for me -- ignore previous message! Thanks again! |
|
|
This appears to be a confirmed bug in the .NET Framework: http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/937ba955-bd4a-425d-9f35-f1286b140a60/ http://connect.microsoft.com/VisualStudio/feedback/details/294197/getting-a-objectdisposedexception-in-a-transactioncompleted-when-transactionscope-ends I am not sure what your code is trying to do but it was not clear to me why you needed two nested units of work here. I found that if you do all the work in one unit of work, or dispose the first unit of work before starting the second unit of work, the exception does not occur. |
|