Distributed Transactions

Topics: Customizing Orchard, General, Troubleshooting
Aug 10, 2011 at 5:58 AM

I am using Application Services for manage users through API. All services works in transactional environment and supports distributed transactions.
After calling following line IUser newUser = this.MembershipService.CreateUser(userInfo); Orchard trying commit transaction using native TransactionManager but it raises exception Cannot access a disposed object. Object name: 'TransactionScope'.
If disable service to accept distributed transactions in methods TransactionScopeRequired = false everything works fine but  there is risk of loss of integrity. Is there a way to avoid exception?

Here example of code:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, TransactionIsolationLevel = IsolationLevel.ReadCommitted, ReleaseServiceInstanceOnTransactionComplete = false)] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class MembershipManagerService : IMembershipManagerService { protected IMembershipService MembershipService { get; private set; } protected IRoleService RoleService { get; private set; } protected IOrchardServices OrchardServices { get; private set; } protected IRepository<UserRolesPartRecord> UserRoleRepository { get; private set; } public MembershipManagerService(IMembershipService membershipService, IRoleService roleService, IRepository<UserRolesPartRecord> userRoleRepository, IOrchardServices orchardServices) { this.MembershipService = membershipService; this.RoleService = roleService; this.UserRoleRepository = userRoleRepository; this.OrchardServices = orchardServices; } [OperationBehavior(TransactionScopeRequired = true)] public bool CreateUser(string userName, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved) { IUser existingUser = this.MembershipService.GetUser(userName); if (existingUser != null) return false; CreateUserParams userInfo = new CreateUserParams(userName, password, email, passwordQuestion, passwordAnswer, isApproved); IUser newUser = this.MembershipService.CreateUser(userInfo); return (newUser != null); } }

Here piece of code from Orchard's TransactionManager class where exception is raised

void IDisposable.Dispose() {
            if (_scope != null) {
                if (!_cancelled) {
                    Logger.Debug("Marking transaction as complete");
                    _scope.Complete(); // Here exception Cannot access a disposed object. Object name: 'TransactionScope'.
                }

                Logger.Debug("Final work for transaction being performed");
                _scope.Dispose();
                Logger.Debug("Transaction disposed");
            }
        }

 

Coordinator
Aug 10, 2011 at 7:56 PM

Try to isolate your work out of the Orchard ambient transaction (see http://orchard.codeplex.com/discussions/266506)

Aug 11, 2011 at 6:21 AM
bertrandleroy wrote:

Try to isolate your work out of the Orchard ambient transaction (see http://orchard.codeplex.com/discussions/266506)

  Thanks for your answer. TransactionScopeRequired = false gives same result in my case. But it means that my services (I have another set of WCF SOAP services on another servers) and Orchard's services is working under different transactions. Am I right? In principle this is no big deal and it works.

  Thanks for your help and great product!