⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractcollectionpersister.cs

📁 NHibernate NET开发者所需的
💻 CS
📖 第 1 页 / 共 4 页
字号:
using System;
using System.Collections;
using System.Data;
using System.Text;
using Iesi.Collections;
using log4net;
using NHibernate.AdoNet;
using NHibernate.Cache;
using NHibernate.Cache.Entry;
using NHibernate.Cfg;
using NHibernate.Collection;
using NHibernate.Engine;
using NHibernate.Exceptions;
using NHibernate.Id;
using NHibernate.Impl;
using NHibernate.Loader.Collection;
using NHibernate.Mapping;
using NHibernate.Metadata;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
using NHibernate.Type;
using NHibernate.Util;
using Array=NHibernate.Mapping.Array;
using System.Collections.Generic;
using NHibernate.SqlTypes;
using System.Data.Common;

namespace NHibernate.Persister.Collection
{
	/// <summary>
	/// Summary description for AbstractCollectionPersister.
	/// </summary>
	public abstract class AbstractCollectionPersister : ICollectionMetadata, ISqlLoadableCollection
	{
		private readonly string role;

		#region SQL statements

		private readonly SqlCommandInfo sqlDeleteString;
		private readonly SqlCommandInfo sqlInsertRowString;
		private readonly SqlCommandInfo sqlUpdateRowString;
		private readonly SqlCommandInfo sqlDeleteRowString;
		private readonly SqlString sqlSelectSizeString;
		private readonly SqlString sqlSelectRowByIndexString;
		private readonly SqlString sqlDetectRowByIndexString;
		private readonly SqlString sqlDetectRowByElementString;
		private readonly string sqlOrderByString;
		protected readonly string sqlWhereString;
		private readonly string sqlOrderByStringTemplate;
		private readonly string sqlWhereStringTemplate;
		private readonly bool hasOrder;
		private readonly bool hasWhere;
		private readonly int baseIndex;
		private readonly string nodeName;
		private readonly string elementNodeName;
		private readonly string indexNodeName;

		protected internal bool indexContainsFormula;
		protected internal bool elementIsPureFormula;

		#endregion

		#region Types

		private readonly IType keyType;
		private readonly IType indexType;
		private readonly IType elementType;
		private readonly IType identifierType;

		#endregion

		#region Columns

		protected readonly string[] keyColumnNames;
		protected readonly string[] indexColumnNames;
		protected readonly string[] indexFormulaTemplates;
		protected readonly string[] indexFormulas;
		protected readonly bool[] indexColumnIsSettable;
		protected readonly string[] elementColumnNames;
		protected readonly string[] elementFormulaTemplates;
		protected readonly string[] elementFormulas;
		protected readonly bool[] elementColumnIsSettable;
		protected readonly bool[] elementColumnIsInPrimaryKey;
		private readonly string[] indexColumnAliases;
		protected readonly string[] elementColumnAliases;
		private readonly string[] keyColumnAliases;
		private readonly string identifierColumnName;
		private readonly string identifierColumnAlias;

		#endregion

		protected readonly string qualifiedTableName;
		private readonly string queryLoaderName;

		private readonly bool isPrimitiveArray;
		private readonly bool isArray;
		private readonly bool hasIndex;
		protected readonly bool hasIdentifier;
		protected readonly bool isPostInsertIdentifier;
		private readonly bool isLazy;
		private readonly bool isExtraLazy;
		private readonly bool isInverse;
		private readonly bool isMutable;
		private readonly bool isVersioned;
		protected readonly int batchSize;
		private readonly FetchMode fetchMode;
		private readonly bool hasOrphanDelete;
		private readonly bool subselectLoadable;

		#region Extra information about the element type

		private readonly System.Type elementClass;
		private readonly string entityName;

		#endregion

		private readonly Dialect.Dialect dialect;
		private readonly ISQLExceptionConverter sqlExceptionConverter;
		private readonly ISessionFactoryImplementor factory;
		private readonly IEntityPersister ownerPersister;
		private readonly IIdentifierGenerator identifierGenerator;
		private readonly IPropertyMapping elementPropertyMapping;
		private readonly IEntityPersister elementPersister;
		private readonly ICacheConcurrencyStrategy cache;
		private readonly CollectionType collectionType;
		private ICollectionInitializer initializer;

		private readonly ICacheEntryStructure cacheEntryStructure;

		// dynamic filters for the collection
		private readonly FilterHelper filterHelper;

		#region Dynamic filters specifically for many-to-many inside the collection

		private readonly FilterHelper manyToManyFilterHelper;
		private readonly string manyToManyWhereString;
		private readonly string manyToManyWhereTemplate;
		private readonly string manyToManyOrderByString;
		private readonly string manyToManyOrderByTemplate;

		#endregion

		#region Custom SQL

		private readonly bool insertCallable;
		private readonly bool updateCallable;
		private readonly bool deleteCallable;
		private readonly bool deleteAllCallable;
		private readonly ExecuteUpdateResultCheckStyle insertCheckStyle;
		private readonly ExecuteUpdateResultCheckStyle updateCheckStyle;
		private readonly ExecuteUpdateResultCheckStyle deleteCheckStyle;
		private readonly ExecuteUpdateResultCheckStyle deleteAllCheckStyle;

		#endregion

		private readonly string[] spaces;

		private readonly IDictionary collectionPropertyColumnAliases = new Hashtable();
		private readonly IDictionary collectionPropertyColumnNames = new Hashtable();

		private static readonly ILog log = LogManager.GetLogger(typeof(ICollectionPersister));

		public AbstractCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache,
																			 Configuration cfg, ISessionFactoryImplementor factory)
		{
			this.factory = factory;
			this.cache = cache;
			if (factory.Settings.IsStructuredCacheEntriesEnabled)
				cacheEntryStructure = collection.IsMap
																? (ICacheEntryStructure)new StructuredMapCacheEntry()
																: (ICacheEntryStructure)new StructuredCollectionCacheEntry();
			else
				cacheEntryStructure = new UnstructuredCacheEntry();

			dialect = factory.Dialect;
			sqlExceptionConverter = factory.SQLExceptionConverter;
			collectionType = collection.CollectionType;
			role = collection.Role;
			entityName = collection.OwnerEntityName;
			ownerPersister = factory.GetEntityPersister(entityName);
			queryLoaderName = collection.LoaderName;
			nodeName = collection.NodeName;
			isMutable = collection.IsMutable;

			Table table = collection.CollectionTable;
			fetchMode = collection.Element.FetchMode;
			elementType = collection.Element.Type;
			isPrimitiveArray = collection.IsPrimitiveArray;
			isArray = collection.IsArray;
			subselectLoadable = collection.IsSubselectLoadable;
			qualifiedTableName = table.GetQualifiedName(dialect, factory.DefaultSchema);

			int spacesSize = 1 + collection.SynchronizedTables.Count;
			spaces = new string[spacesSize];
			int ispa = 0;
			spaces[ispa++] = qualifiedTableName;
			foreach (string s in collection.SynchronizedTables)
				spaces[ispa++] = s;

			sqlOrderByString = collection.OrderBy;
			hasOrder = sqlOrderByString != null;
			sqlOrderByStringTemplate = hasOrder
																	? Template.RenderOrderByStringTemplate(sqlOrderByString, dialect,
																																				 factory.SQLFunctionRegistry)
																	: null;
			sqlWhereString = !string.IsNullOrEmpty(collection.Where) ? '(' + collection.Where + ')' : null;
			hasWhere = sqlWhereString != null;
			sqlWhereStringTemplate = hasWhere
																? Template.RenderWhereStringTemplate(sqlWhereString, dialect, factory.SQLFunctionRegistry)
																: null;
			hasOrphanDelete = collection.HasOrphanDelete;
			int batch = collection.BatchSize;
			if (batch == -1)
				batch = factory.Settings.DefaultBatchFetchSize;
			batchSize = batch;

			isVersioned = collection.IsOptimisticLocked;

			keyType = collection.Key.Type;
			int keySpan = collection.Key.ColumnSpan;
			keyColumnNames = new string[keySpan];
			keyColumnAliases = new string[keySpan];
			int k = 0;
			foreach (Column col in collection.Key.ColumnIterator)
			{
				keyColumnNames[k] = col.GetQuotedName(dialect);
				keyColumnAliases[k] = col.GetAlias(dialect);
				k++;
			}
			ISet distinctColumns = new HashedSet();
			CheckColumnDuplication(distinctColumns, collection.Key.ColumnIterator);

			#region Element
			IValue element = collection.Element;
			if (!collection.IsOneToMany)
				CheckColumnDuplication(distinctColumns, element.ColumnIterator);

			string elemNode = collection.ElementNodeName;
			if (elementType.IsEntityType)
			{
				string _entityName = ((EntityType)elementType).GetAssociatedEntityName();
				elementPersister = factory.GetEntityPersister(_entityName);
				if (elemNode == null)
				{
					elemNode = cfg.GetClassMapping(_entityName).NodeName;
				}
				// NativeSQL: collect element column and auto-aliases
			}
			else
			{
				elementPersister = null;
			}
			elementNodeName = elemNode;

			int elementSpan = element.ColumnSpan;
			elementColumnAliases = new string[elementSpan];
			elementColumnNames = new string[elementSpan];
			elementFormulaTemplates = new string[elementSpan];
			elementFormulas = new string[elementSpan];
			elementColumnIsSettable = new bool[elementSpan];
			elementColumnIsInPrimaryKey = new bool[elementSpan];
			bool isPureFormula = true;
			bool hasNotNullableColumns = false;
			int j = 0;
			foreach (ISelectable selectable in element.ColumnIterator)
			{
				elementColumnAliases[j] = selectable.GetAlias(dialect);
				if (selectable.IsFormula)
				{
					Formula form = (Formula)selectable;
					elementFormulaTemplates[j] = form.GetTemplate(dialect, factory.SQLFunctionRegistry);
					elementFormulas[j] = form.FormulaString;
				}
				else
				{
					Column col = (Column)selectable;
					elementColumnNames[j] = col.GetQuotedName(dialect);
					elementColumnIsSettable[j] = true;
					elementColumnIsInPrimaryKey[j] = !col.IsNullable;
					if (!col.IsNullable)
						hasNotNullableColumns = true;

					isPureFormula = false;
				}
				j++;
			}
			elementIsPureFormula = isPureFormula;

			//workaround, for backward compatibility of sets with no
			//not-null columns, assume all columns are used in the
			//row locator SQL
			if (!hasNotNullableColumns)
				ArrayHelper.Fill(elementColumnIsInPrimaryKey, true);

			#endregion

			#region INDEX AND ROW SELECT
			hasIndex = collection.IsIndexed;
			if (hasIndex)
			{
				// NativeSQL: collect index column and auto-aliases
				IndexedCollection indexedCollection = (IndexedCollection)collection;
				indexType = indexedCollection.Index.Type;
				int indexSpan = indexedCollection.Index.ColumnSpan;
				indexColumnNames = new string[indexSpan];
				indexFormulaTemplates = new string[indexSpan];
				indexFormulas = new string[indexSpan];
				indexColumnIsSettable = new bool[indexSpan];
				indexColumnAliases = new string[indexSpan];
				bool hasFormula = false;
				int i = 0;
				foreach (ISelectable selectable in indexedCollection.Index.ColumnIterator)
				{
					indexColumnAliases[i] = selectable.GetAlias(dialect);
					if (selectable.IsFormula)
					{
						Formula indexForm = (Formula)selectable;
						indexFormulaTemplates[i] = indexForm.GetTemplate(dialect, factory.SQLFunctionRegistry);
						indexFormulas[i] = indexForm.FormulaString;
						hasFormula = true;
					}
					else
					{
						Column indexCol = (Column)selectable;
						indexColumnNames[i] = indexCol.GetQuotedName(dialect);
						indexColumnIsSettable[i] = true;
					}
					i++;
				}
				indexContainsFormula = hasFormula;
				baseIndex = indexedCollection.IsList ? ((List)indexedCollection).BaseIndex : 0;

				indexNodeName = indexedCollection.IndexNodeName;
				CheckColumnDuplication(distinctColumns, indexedCollection.Index.ColumnIterator);
			}
			else
			{
				indexContainsFormula = false;
				indexColumnIsSettable = null;
				indexFormulaTemplates = null;
				indexFormulas = null;
				indexType = null;
				indexColumnNames = null;
				indexColumnAliases = null;
				baseIndex = 0;
				indexNodeName = null;
			}

			hasIdentifier = collection.IsIdentified;
			if (hasIdentifier)
			{
				if (collection.IsOneToMany)
				{
					throw new MappingException("one-to-many collections with identifiers are not supported.");
				}
				IdentifierCollection idColl = (IdentifierCollection)collection;
				identifierType = idColl.Identifier.Type;

				Column col = null;
				foreach (Column column in idColl.Identifier.ColumnIterator)
				{
					col = column;
					break;
				}

				identifierColumnName = col.GetQuotedName(dialect);
				identifierColumnAlias = col.GetAlias(dialect);
				identifierGenerator =
					idColl.Identifier.CreateIdentifierGenerator(factory.Dialect, factory.Settings.DefaultCatalogName,
																											factory.Settings.DefaultSchemaName, null);
				isPostInsertIdentifier = (identifierGenerator as IPostInsertIdentifierGenerator) != null;
				CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnIterator);
			}
			else
			{
				identifierType = null;
				identifierColumnName = null;
				identifierColumnAlias = null;
				identifierGenerator = null;
			}

			#endregion

			#region GENERATE THE SQL
			//shouldInsertIdentifier = hasIdentifier && !(identifierGenerator is NHibernate.Id.IdentityGenerator);

			sqlInsertRowString = GenerateInsertRowString();
			if (collection.CustomSQLInsert == null)
			{
				insertCallable = false;
				insertCheckStyle = ExecuteUpdateResultCheckStyle.Count;
			}
			else
			{
				sqlInsertRowString = new SqlCommandInfo(collection.CustomSQLInsert, sqlInsertRowString.ParameterTypes);
				insertCallable = collection.IsCustomInsertCallable;
				insertCheckStyle = collection.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLInsert, insertCallable);
			}

			sqlUpdateRowString = GenerateUpdateRowString();
			if (collection.CustomSQLUpdate == null)
			{
				updateCallable = false;
				updateCheckStyle = ExecuteUpdateResultCheckStyle.Count;
			}
			else
			{
				sqlUpdateRowString = new SqlCommandInfo(collection.CustomSQLUpdate, sqlUpdateRowString.ParameterTypes);
				updateCallable = collection.IsCustomUpdateCallable;
				updateCheckStyle = collection.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLUpdate, updateCallable);
			}

			sqlDeleteRowString = GenerateDeleteRowString();
			if (collection.CustomSQLDelete == null)
			{
				deleteCallable = false;
				deleteCheckStyle = ExecuteUpdateResultCheckStyle.None;
			}
			else
			{
				sqlDeleteRowString = new SqlCommandInfo(collection.CustomSQLDelete, sqlDeleteRowString.ParameterTypes);
				deleteCallable = collection.IsCustomDeleteCallable;
				deleteCheckStyle = ExecuteUpdateResultCheckStyle.None;
			}

			sqlDeleteString = GenerateDeleteString();
			if (collection.CustomSQLDeleteAll == null)
			{
				deleteAllCallable = false;
				deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None;
			}
			else
			{
				sqlDeleteString = new SqlCommandInfo(collection.CustomSQLDeleteAll, sqlDeleteString.ParameterTypes);
				deleteAllCallable = collection.IsCustomDeleteAllCallable;
				deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None;
			}

			sqlSelectSizeString = GenerateSelectSizeString(collection.IsIndexed && !collection.IsMap);
			sqlDetectRowByIndexString = GenerateDetectRowByIndexString();
			sqlDetectRowByElementString = GenerateDetectRowByElementString();
			sqlSelectRowByIndexString = GenerateSelectRowByIndexString();

			LogStaticSQL();

			#endregion

			isLazy = collection.IsLazy;
			isExtraLazy = collection.ExtraLazy;
			isInverse = collection.IsInverse;

			if (collection.IsArray)
			{
				elementClass = ((Array)collection).ElementClass;
			}
			else
			{

⌨️ 快捷键说明

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