/// <summary>
        /// 锁定一个给定的聚合根,数据库级别的锁;
        /// 该方法内部不需要考虑事务,因为框架在调用该方法之前已经确保当前事务是开启的;
        /// 默认实现是通过ROWLOCK+UPDLOCK的方式实现行级锁;
        /// </summary>
        protected virtual long LockAggregateRootAfterTransactionStarted(string aggregateRootId)
        {
            var aggregateRootEventType = _aggregateRootEventTypeProvider.GetAggregateRootEventType(typeof(T));
            var aggregateRootName      = GetAggregateRootName();

            DetachedCriteria detachedCriteria = DetachedCriteria.For(aggregateRootEventType)
                                                .Add(Restrictions.Eq("AggregateRootName", aggregateRootName))
                                                .Add(Restrictions.Eq("AggregateRootId", aggregateRootId))
                                                .Add(Subqueries.PropertyEq("Version",
                                                                           DetachedCriteria.For(aggregateRootEventType)
                                                                           .SetProjection(Projections.Max("Version"))
                                                                           .Add(Restrictions.Eq("AggregateRootName", aggregateRootName))
                                                                           .Add(Restrictions.Eq("AggregateRootId", aggregateRootId))));

            detachedCriteria.SetLockMode(LockMode.Upgrade);
            var criteria = detachedCriteria.GetExecutableCriteria(OpenSession());

            var eventList = typeof(EventQueryHelper).GetMethod("GetList").MakeGenericMethod(aggregateRootEventType).Invoke(new EventQueryHelper(), new object[] { criteria }) as IList;

            if (eventList != null && eventList.Count > 0)
            {
                return((long)((AggregateRootEvent)eventList[0]).Version);
            }
            return(0);
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Builds a <see cref="DetachedCriteria" /> from the given <see cref="IMorphableFlowQuery" /> query.
        /// </summary>
        /// <param name="query">
        ///     The query from which to build a <see cref="ICriteria" />.
        /// </param>
        /// <typeparam name="TSource">
        ///     The <see cref="System.Type" /> of the underlying entity for the given query.
        /// </typeparam>
        /// <returns>
        ///     The built <see cref="DetachedCriteria" />.
        /// </returns>
        public virtual DetachedCriteria Build <TSource>(IMorphableFlowQuery query)
        {
            if (query == null)
            {
                throw new ArgumentNullException("query");
            }

            DetachedCriteria criteria = DetachedCriteria.For <TSource>(query.Alias);

            foreach (Join join in query.Joins)
            {
                criteria.CreateAlias(join.Property, join.Alias, join.JoinType, join.WithClause);
            }

            foreach (ICriterion criterion in query.Criterions)
            {
                criteria.Add(criterion);
            }

            foreach (Lock queryLock in query.Locks)
            {
                if (queryLock.Alias == null)
                {
                    criteria.SetLockMode(queryLock.LockMode);
                }
                else
                {
                    criteria.SetLockMode(queryLock.Alias, queryLock.LockMode);
                }
            }

            bool skips = query.ResultsToSkip.HasValue && query.ResultsToSkip.Value > 0;

            if (skips)
            {
                criteria.SetFirstResult(query.ResultsToSkip.Value);
            }

            bool takes = query.ResultsToTake.HasValue && query.ResultsToTake.Value > 0;

            if (takes)
            {
                criteria.SetMaxResults(query.ResultsToTake.Value);
            }

            if (query.IsCacheable)
            {
                criteria.SetCacheable(true);

                if (query.CacheMode.HasValue)
                {
                    criteria.SetCacheMode(query.CacheMode.Value);
                }

                if (!string.IsNullOrEmpty(query.CacheRegion))
                {
                    criteria.SetCacheRegion(query.CacheRegion);
                }
            }

            criteria
            .SetProjection
            (
                GetProjection(query)
            );

            if (query.ResultTransformer != null)
            {
                criteria.SetResultTransformer(query.ResultTransformer);
            }

            if (query.Orders.Count > 0 && (skips || takes))
            {
                foreach (OrderByStatement statement in query.Orders)
                {
                    if (statement.IsBasedOnSource)
                    {
                        criteria.AddOrder(statement.Order);
                    }
                }
            }

            return(criteria);
        }