using System; using System.Runtime.InteropServices; using System.Threading.Tasks; namespace Abp.Domain.Uow { /// /// This handle is used for innet unit of work scopes. /// A inner unit of work scope actually uses outer unit of work scope /// and has no effect on call. /// But if it's not called, an exception is thrown at end of the UOW to rollback the UOW. /// internal class InnerUnitOfWorkCompleteHandle : IUnitOfWorkCompleteHandle { public const string DidNotCallCompleteMethodExceptionMessage = "Did not call Complete method of a unit of work."; private volatile bool _isCompleteCalled; private volatile bool _isDisposed; public void Complete() { _isCompleteCalled = true; } public Task CompleteAsync() { _isCompleteCalled = true; return Task.FromResult(0); } public void Dispose() { if (_isDisposed) { return; } _isDisposed = true; if (!_isCompleteCalled) { if (HasException()) { return; } throw new AbpException(DidNotCallCompleteMethodExceptionMessage); } } private static bool HasException() { try { return Marshal.GetExceptionCode() != 0; } catch (Exception) { return false; } } } }