/// <summary>
        /// Execute task.
        /// </summary>
        /// <typeparam name="T">Task return type.</typeparam>
        /// <param name="context">The context of this task.</param>
        /// <returns>
        /// Task result.
        /// </returns>
        public virtual T Execute <T>(ExecutionContext <T> context)
        {
            int i = 0;

            while (true)
            {
                Session          session     = null;
                TransactionScope tran        = null;
                bool             needBreak   = false;
                Transaction      transaction = null;
                try
                {
                    T            result;
                    SessionScope sessionScope = null;
                    try
                    {
                        try
                        {
                            IsolationLevel    isolationLevel     = context.IsolationLevel;
                            SystemTransaction currentTransaction = SystemTransaction.Current;
                            if (isolationLevel == IsolationLevel.Unspecified && currentTransaction != null)
                            {
                                isolationLevel = currentTransaction.IsolationLevel;
                            }
                            session = SessionScope.CurrentSession;
                            if (session == null)
                            {
                                session      = context.Domain.OpenSession();
                                sessionScope = session.Activate();
                            }
                            if (currentTransaction != null && session.Transaction != null)
                            {
                                session.EnsureTransactionIsStarted();
                            }
                            tran = (currentTransaction != null && currentTransaction.TransactionInformation.DistributedIdentifier != Guid.Empty) ||
                                   (session.Transaction != null && session.Transaction.IsDisconnected)
                       ? session.OpenTransaction(isolationLevel)
                       : session.OpenTransaction(context.TransactionOpenMode, isolationLevel);
                            transaction = session.Transaction;
                            result      = context.Function(session);
                            tran.Complete();
                        }
                        finally
                        {
                            try
                            {
                                tran.DisposeSafely();
                            }
                            catch (StorageException e)
                            {
                                if (e.InnerException == null || !(e.InnerException is InvalidOperationException) ||
                                    e.InnerException.Source != "System.Data")
                                {
                                    throw;
                                }
                                if (tran.Transaction.IsNested)
                                {
                                    needBreak = true;
                                }
                            }
                        }
                    }
                    finally
                    {
                        sessionScope.DisposeSafely();
                        if (SessionScope.CurrentSession != session)
                        {
                            session.DisposeSafely();
                        }
                    }
                    return(result);
                }
                catch (Exception e)
                {
                    if ((SystemTransaction.Current != null &&
                         SystemTransaction.Current.TransactionInformation.DistributedIdentifier != Guid.Empty) ||
                        (transaction != null && (transaction.State == TransactionState.Active || transaction.IsDisconnected)))
                    {
                        throw;
                    }
                    if (e is RollbackTransactionException)
                    {
                        return(default(T));
                    }
                    i++;
                    if (needBreak || !HandleException(new ExecuteErrorEventArgs(e, session, transaction, i)))
                    {
                        throw;
                    }
                }
            }
        }