basiccollectionjoinwalker.cs

来自「NHibernate NET开发者所需的」· CS 代码 · 共 109 行

CS
109
字号
using System;
using System.Collections.Generic;
using Iesi.Collections;
using NHibernate.Engine;
using NHibernate.Persister.Collection;
using NHibernate.SqlCommand;
using NHibernate.Type;
using NHibernate.Util;

namespace NHibernate.Loader.Collection
{
	/// <summary>
	/// Walker for collections of values and many-to-many associations
	/// </summary>
	public class BasicCollectionJoinWalker : CollectionJoinWalker
	{
		private readonly IQueryableCollection collectionPersister;

		public BasicCollectionJoinWalker(IQueryableCollection collectionPersister, int batchSize,
			SqlString subquery, ISessionFactoryImplementor factory, IDictionary<string, IFilter> enabledFilters)
			: base(factory, enabledFilters)
		{
			this.collectionPersister = collectionPersister;
			string alias = GenerateRootAlias(collectionPersister.Role);

			WalkCollectionTree(collectionPersister, alias);

			IList<OuterJoinableAssociation> allAssociations = new List<OuterJoinableAssociation>(associations);

			allAssociations.Add(
				new OuterJoinableAssociation(collectionPersister.CollectionType, null, null, alias, JoinType.LeftOuterJoin, Factory,
				                             enabledFilters));

			InitPersisters(allAssociations, LockMode.None);
			InitStatementString(alias, batchSize, subquery);
		}

		private void InitStatementString(string alias, int batchSize, SqlString subquery)
		{
			int joins = CountEntityPersisters(associations);
			int collectionJoins = CountCollectionPersisters(associations) + 1;
			Suffixes = BasicLoader.GenerateSuffixes(joins);
			CollectionSuffixes = BasicLoader.GenerateSuffixes(joins, collectionJoins);

			SqlStringBuilder whereString = WhereString(alias, collectionPersister.KeyColumnNames, subquery, batchSize);

			string manyToManyOrderBy = string.Empty;
			string filter = collectionPersister.FilterFragment(alias, EnabledFilters);

			if (collectionPersister.IsManyToMany)
			{
				// from the collection of associations, locate OJA for the
				// ManyToOne corresponding to this persister to fully
				// define the many-to-many; we need that OJA so that we can
				// use its alias here
				// TODO : is there a better way here?
				IAssociationType associationType = (IAssociationType)collectionPersister.ElementType;
				foreach (OuterJoinableAssociation oja in associations)
				{
					if (oja.JoinableType == associationType)
					{
						// we found it
						filter += collectionPersister.GetManyToManyFilterFragment(oja.RHSAlias, EnabledFilters);
						manyToManyOrderBy += collectionPersister.GetManyToManyOrderByString(oja.RHSAlias);
					}
				}
			}

			whereString.Insert(0, StringHelper.MoveAndToBeginning(filter));
			JoinFragment ojf = MergeOuterJoins(associations);

			SqlSelectBuilder select =
				new SqlSelectBuilder(Factory)
				.SetSelectClause(collectionPersister.SelectFragment(alias, CollectionSuffixes[0])
				                                              + SelectString(associations))
				.SetFromClause(collectionPersister.TableName, alias)
				.SetWhereClause(whereString.ToSqlString())
				.SetOuterJoins(ojf.ToFromFragmentString, ojf.ToWhereFragmentString);

			select.SetOrderByClause(OrderBy(associations, MergeOrderings(collectionPersister.GetSQLOrderByString(alias), manyToManyOrderBy)));

			if (Factory.Settings.IsCommentsEnabled)
				select.SetComment("load collection " + collectionPersister.Role);

			SqlString = select.ToSqlString();
		}

		/// <summary>
		/// We can use an inner join for first many-to-many association
		/// </summary>
		protected JoinType GetJoinType(IAssociationType type, FetchMode config, String path, ISet visitedAssociations,
			string lhsTable, string[] lhsColumns, bool nullable, int currentDepth)
		{
			JoinType joinType = base.GetJoinType(type, config, path, lhsTable, lhsColumns, nullable, currentDepth, null);

			//we can use an inner join for the many-to-many
			if (joinType == JoinType.LeftOuterJoin && string.Empty.Equals(path))
			{
				joinType = JoinType.InnerJoin;
			}
			return joinType;
		}

		public override string ToString()
		{
			return GetType().FullName + '(' + collectionPersister.Role + ')';
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?