Esempio n. 1
0
        /// <summary>
        ///     Notification de la fin de la session
        /// </summary>
        private ISessionInformation OnSessionCompleted(SessionLocalInfo info, IEnumerable <IEventNotifier> notifiers, IExecutionResultInternal messages)
        {
            DebugContract.Requires(notifiers != null, "notifiers");
            // On fait une copie de la session car les événements peuvent
            // être souscrits dans un autre thread
            var sessionContext = new SessionInformation(this, info, SessionDataContext.TrackingData, messages);

            try
            {
                // Notifications via RX.
                foreach (var notifier in notifiers)
                {
                    notifier.NotifySessionCompleted(sessionContext, SessionContext);
                }

                // Déclenchement des événements
                // D'abord évenement hard
                var tmp = Completing;
                if (tmp != null)
                {
                    tmp(this, new SessionCompletingEventArgs(sessionContext));
                }
            }
            catch (Exception ex)
            {
                // Si une erreur survient dans une notification, on l'intercepte
                Log(new DiagnosticMessage(MessageType.Error, ex.Message, "SessionTerminated", SessionDataContext.InValidationProcess, null, ex));
            }
            return(sessionContext);
        }
Esempio n. 2
0
        private ExecutionResult ExecuteConstraints(SessionDataContext ctx, SessionLocalInfo currentInfo)
        {
            var messages = ctx.MessageList;

            // Notification des événements.
            // La notification se fait encore dans le scope actif

            // A partir d'ici, les événements (issues des commandes) NE SONT PLUS pris en compte car si une nouvelle commande est émise
            // il faut pouvoir :
            //  1 - exécuter les contraintes sur les nouvelles modifications.
            //  2 - renvoyer les nouveaux évents.
            // Ce qui n'est pas possible à partir d'ici puisqu'on est dans le processus gérant ces cas.
            //
            // Si on veut générer d'autres events, il faut s'abonner dans un autre thread (pour pouvoir créer une nouvelle session)
            ctx.ReadOnly = true;
            var hasInvolvedElements = false;

            using (CodeMarker.MarkBlock("Session.PrepareInvolvedElements"))
            {
                // Récupération des éléments impactés au cours de la session
                // Ne pas le faire lors des chargements des metadonnées  car :
                //  1 - Il n'y a pas de contraintes sur les metadonnées
                //  2 - En cas de chargement d'une extension, les métadonnées ne sont pas encore accessibles et cela fait planter le code.
                hasInvolvedElements = SessionDataContext.TrackingData.PrepareModelElements(IsAborted, (currentInfo.Mode & SessionMode.LoadingSchema) == SessionMode.LoadingSchema);
            }

            // Validation implicite sur les éléments modifiés au cours de la session
            // Ce code ne doit pas se faire lorsqu'on charge les metadonnées
            if (hasInvolvedElements && (currentInfo.Mode & SessionMode.SkipConstraints) != SessionMode.SkipConstraints)
            {
                try
                {
                    // Vérification des contraintes implicites
                    using (CodeMarker.MarkBlock("Session.CheckConstraints"))
                    {
                        CheckConstraints(InvolvedElements);
                    }
                    // Une contrainte peut entrainer un rollback de la transaction
                    // si il retourne une erreur dans result.
                    ctx.Aborted = ctx.MessageList != null && ctx.MessageList.HasErrors;
                }
                catch (Exception ex)
                {
                    ctx.Aborted = true;
                    var exception = ex;
                    if (exception is AggregateException)
                    {
                        exception = ((AggregateException)ex).InnerException;
                    }
                    Log(new DiagnosticMessage(MessageType.Error, exception.Message, ExceptionMessages.Diagnostic_ConstraintsProcessError, SessionDataContext.InValidationProcess, null, exception));
                }
            }
            return(messages);
        }
Esempio n. 3
0
        internal SessionInformation(Session session, SessionLocalInfo info, ISessionTrackingData trackingData, IExecutionResultInternal messages)
        {
            DebugContract.Requires(session, "session");
            DebugContract.Requires(trackingData);

            _context          = session.SessionContext;
            TrackingData      = trackingData;
            CancellationToken = session.CancellationToken;
            IsAborted         = session.IsAborted;
            IsNested          = session.IsNested;
            Store             = session.Store;
            IsReadOnly        = session.IsReadOnly;
            Mode               = info.Mode;
            OriginStoreId      = info.OriginStoreId;
            SessionId          = session.SessionId;
            DefaultDomainModel = info.DefaultDomainModel;
            _contextInfos      = info.Infos;
            Events             = session.Events.ToList();
            if (messages != null)
            {
                HasErrors   = messages.HasErrors;
                HasWarnings = messages.HasWarnings;
            }
        }
Esempio n. 4
0
        private Tuple <ExecutionResult, ISessionInformation> CompleteTopLevelTransaction(IEnumerable <IEventNotifier> notifiers, SessionDataContext ctx, SessionLocalInfo currentInfo)
        {
            // Sauvegarde des références vers les objets qui sont utilisés aprés que les données de la session auront été supprimées
            ExecutionResult     messages    = null;
            ISessionInformation sessionInfo = null;

            // Il ne peut pas y avoir d'erreur dans cette partie de code
            try
            {
                ctx.Disposing = true;

                // Si la session était en lecture seule, on simplifie les traitements
                // Pas de validation
                if (!ctx.ReadOnly)
                {
                    messages = ExecuteConstraints(ctx, currentInfo);
                }

                // Contexte en lecture seule de la session mais tjs dans le scope
                // Envoi des events même en read-only pour s'assurer que le OnSessionCompleted soit bien notifié
                if (!ctx.CancellationToken.IsCancellationRequested)
                {
                    using (CodeMarker.MarkBlock("Session.OnSessionCompleted"))
                    {
                        sessionInfo = OnSessionCompleted(currentInfo, notifiers, messages);
                    }
                }

                // Si tout va bien, on commite
                if (!IsAborted && _scope != null && (messages == null || !messages.HasErrors))
                {
                    _scope.Complete();
                }
            }
            catch (Exception ex)
            {
                Log(new DiagnosticMessage(MessageType.Error, ex.Message, ExceptionMessages.Diagnostic_ApplicationError, SessionDataContext.InValidationProcess, null, ex));
            }
            finally
            {
                DisposeSession(ctx);
            }

            return(Tuple.Create(messages ?? ExecutionResult.Empty, sessionInfo));
        }