/// <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); }
/// <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); }