Пример #1
0
        public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model,
                                                  ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory)
        {
            ConstructorInfo pc;

            try
            {
                pc = persisterClass.GetConstructor(CollectionPersisterConstructorArgs);
            }
            catch (Exception e)
            {
                throw new MappingException("Could not get constructor for " + persisterClass.Name, e);
            }

            try
            {
                return((ICollectionPersister)pc.Invoke(new object[] { model, cache, factory }));
            }
            catch (TargetInvocationException tie)
            {
                Exception e = tie.InnerException;
                if (e is HibernateException)
                {
                    throw e;
                }
                else
                {
                    throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e);
                }
            }
            catch (Exception e)
            {
                throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e);
            }
        }
		/// <summary>
		/// Creates a specific Persister - could be a built in or custom persister.
		/// </summary>
		public static IEntityPersister Create(System.Type persisterClass, PersistentClass model,
		                                      ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory,
		                                      IMapping cfg)
		{
			ConstructorInfo pc;
			try
			{
				pc = persisterClass.GetConstructor(PersisterConstructorArgs);
			}
			catch (Exception e)
			{
				throw new MappingException("Could not get constructor for " + persisterClass.Name, e);
			}

			try
			{
				return (IEntityPersister) pc.Invoke(new object[] {model, cache, factory, cfg});
			}
			catch (TargetInvocationException tie)
			{
				Exception e = tie.InnerException;
				if (e is HibernateException)
				{
					throw e;
				}
				else
				{
					throw new MappingException("Could not instantiate persister " + persisterClass.Name, e);
				}
			}
			catch (Exception e)
			{
				throw new MappingException("Could not instantiate persister " + persisterClass.Name, e);
			}
		}
		public BasicCollectionPersister(
			Mapping.Collection collection,
			ICacheConcurrencyStrategy cache,
			ISessionFactoryImplementor factory)
			: base(collection, cache, factory)
		{
		}
Пример #4
0
 public OneToManyPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory)
     : base(collection, cache, cfg, factory)
 {
     cascadeDeleteEnabled = collection.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete;
     keyIsNullable        = collection.Key.IsNullable;
     keyIsUpdateable      = collection.Key.IsUpdateable;
 }
Пример #5
0
		public OneToManyPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory)
			: base(collection, cache, cfg, factory)
		{
			_cascadeDeleteEnabled = collection.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete;
			_keyIsNullable = collection.Key.IsNullable;
			_keyIsUpdateable = collection.Key.IsUpdateable;
		}
 /// <summary>
 /// Attempt to retrieve multiple objects from the Cache
 /// </summary>
 /// <param name="cache">The cache concurrency strategy.</param>
 /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param>
 /// <param name="timestamp">A timestamp prior to the transaction start time</param>
 /// <returns>An array of cached objects or <see langword="null" /></returns>
 /// <exception cref="CacheException"></exception>
 public static object[] GetMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp)
 {
     if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache))
     {
         throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching");
     }
     return(batchableCache.GetMany(keys, timestamp));
 }
 /// <summary>
 /// Attempt to retrieve multiple objects from the Cache
 /// </summary>
 /// <param name="cache">The cache concurrency strategy.</param>
 /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param>
 /// <param name="timestamp">A timestamp prior to the transaction start time</param>
 /// <returns>An array of cached objects or <see langword="null" /></returns>
 /// <exception cref="CacheException"></exception>
 public static object[] GetMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp)
 {
     // PreferMultipleGet yields false if !IBatchableCacheConcurrencyStrategy, no GetMany call should be done
     // in such case.
     return(ReflectHelper
            .CastOrThrow <IBatchableCacheConcurrencyStrategy>(cache, "batching")
            .GetMany(keys, timestamp));
 }
Пример #8
0
 public DiscriminatedSubclassWithDynamicComponentEntityPersister(
     PersistentClass persistentClass,
     ICacheConcurrencyStrategy cache,
     ISessionFactoryImplementor factory,
     IMapping mapping)
     : base(persistentClass, cache, factory, mapping)
 {
 }
 // 6.0 TODO: remove
 internal static bool PreferMultipleGet(this ICacheConcurrencyStrategy cache)
 {
     if (cache is IBatchableCacheConcurrencyStrategy batchableCache)
     {
         return(batchableCache.Cache.PreferMultipleGet);
     }
     return(false);
 }
 // 6.0 TODO: remove
 internal static CacheBase GetCacheBase(this ICacheConcurrencyStrategy cache)
 {
     if (cache is IBatchableCacheConcurrencyStrategy batchableCache)
     {
         return(batchableCache.Cache);
     }
     return(cache.Cache?.AsCacheBase());
 }
Пример #11
0
		/// <summary>
		/// Associates the class name with the cache strategy.
		/// </summary>
		/// <param name="name">The classname of the class to cache.</param>
		/// <param name="cache">The <see cref="ICacheConcurrencyStrategy"/> to use for caching.</param>
		/// <exception cref="MappingException">Thrown when <c>name</c> already has a <c>cache</c> associated with it.</exception>
		public void AddCache( string name, ICacheConcurrencyStrategy cache )
		{
			object old = caches[ name ];
			if( old != null )
			{
				throw new MappingException( "duplicate cache region" );
			}
			caches[ name ] = cache;
		}
 /// <summary>
 /// Attempt to cache objects, after loading them from the database.
 /// </summary>
 /// <param name="cache">The cache concurrency strategy.</param>
 /// <param name="keys">The keys (id) of the objects to put in the Cache.</param>
 /// <param name="values">The objects to put in the cache.</param>
 /// <param name="timestamp">A timestamp prior to the transaction start time.</param>
 /// <param name="versions">The version numbers of the objects we are putting.</param>
 /// <param name="versionComparers">The comparers to be used to compare version numbers</param>
 /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param>
 /// <returns><see langword="true" /> if the objects were successfully cached.</returns>
 /// <exception cref="CacheException"></exception>
 public static bool[] PutMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp,
                              object[] versions, IComparer[] versionComparers, bool[] minimalPuts)
 {
     if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache))
     {
         throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching");
     }
     return(batchableCache.PutMany(keys, values, timestamp, versions, versionComparers, minimalPuts));
 }
Пример #13
0
        /// <summary>
        /// Associates the class name with the cache strategy.
        /// </summary>
        /// <param name="name">The classname of the class to cache.</param>
        /// <param name="cache">The <see cref="ICacheConcurrencyStrategy"/> to use for caching.</param>
        /// <exception cref="MappingException">Thrown when <c>name</c> already has a <c>cache</c> associated with it.</exception>
        public void AddCache(string name, ICacheConcurrencyStrategy cache)
        {
            object old = caches[name];

            if (old != null)
            {
                throw new MappingException("duplicate cache region");
            }
            caches[name] = cache;
        }
Пример #14
0
        private void DoTestMinValueTimestampOnStrategy(ICache cache, ICacheConcurrencyStrategy strategy)
        {
            CacheKey key = CreateCacheKey("key");

            strategy.Cache = cache;
            strategy.Put(key, "value", long.MinValue, 0, null, false);

            Assert.IsNull(strategy.Get(key, long.MinValue), "{0} strategy fails the test", strategy.GetType());
            Assert.IsNull(strategy.Get(key, long.MaxValue), "{0} strategy fails the test", strategy.GetType());
        }
        private async Task DoTestMinValueTimestampOnStrategyAsync(ICache cache, ICacheConcurrencyStrategy strategy, CancellationToken cancellationToken = default(CancellationToken))
        {
            CacheKey key = CreateCacheKey("key");

            strategy.Cache = cache;
            await(strategy.PutAsync(key, "value", long.MinValue, 0, null, false, cancellationToken));

            Assert.IsNull(await(strategy.GetAsync(key, long.MinValue, cancellationToken)), "{0} strategy fails the test", strategy.GetType());
            Assert.IsNull(await(strategy.GetAsync(key, long.MaxValue, cancellationToken)), "{0} strategy fails the test", strategy.GetType());
        }
Пример #16
0
        private void AddToBatch(ICacheConcurrencyStrategy cache, CachePutData data)
        {
            if (!_putBatches.TryGetValue(cache, out var cachePutBatch))
            {
                cachePutBatch = new CachePutBatch(_session, cache);
                _putBatches.Add(cache, cachePutBatch);
            }

            cachePutBatch.Add(data);
        }
Пример #17
0
        public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model,
                                                  ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, Configuration cfg)
        {
            ConstructorInfo pc;
            var             use4Parameters = false;

            try
            {
                pc = persisterClass.GetConstructor(CollectionPersisterConstructorArgs);
                if (pc == null)
                {
                    use4Parameters = true;
                    pc             = persisterClass.GetConstructor(CollectionPersisterConstructor2Args);
                }
            }
            catch (Exception e)
            {
                throw new MappingException("Could not get constructor for " + persisterClass.Name, e);
            }
            if (pc == null)
            {
                var messageBuilder = new StringBuilder();
                messageBuilder.AppendLine("Could not find a public constructor for " + persisterClass.Name + ";");
                messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructorArgs.Length + " parameters of types (in order):");
                System.Array.ForEach(CollectionPersisterConstructorArgs, t => messageBuilder.AppendLine(t.FullName));
                messageBuilder.AppendLine();
                messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructor2Args.Length + " parameters of types (in order):");
                System.Array.ForEach(CollectionPersisterConstructor2Args, t => messageBuilder.AppendLine(t.FullName));
                throw new MappingException(messageBuilder.ToString());
            }
            try
            {
                if (!use4Parameters)
                {
                    return((ICollectionPersister)pc.Invoke(new object[] { model, cache, factory }));
                }
                return((ICollectionPersister)pc.Invoke(new object[] { model, cache, cfg, factory }));
            }
            catch (TargetInvocationException tie)
            {
                Exception e = tie.InnerException;
                if (e is HibernateException)
                {
                    throw e;
                }
                else
                {
                    throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e);
                }
            }
            catch (Exception e)
            {
                throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e);
            }
        }
 /// <summary>
 /// Attempt to retrieve multiple objects from the Cache
 /// </summary>
 /// <param name="cache">The cache concurrency strategy.</param>
 /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param>
 /// <param name="timestamp">A timestamp prior to the transaction start time</param>
 /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
 /// <returns>An array of cached objects or <see langword="null" /></returns>
 /// <exception cref="CacheException"></exception>
 public static Task <object[]> GetManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp, CancellationToken cancellationToken)
 {
     if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache))
     {
         throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching");
     }
     if (cancellationToken.IsCancellationRequested)
     {
         return(Task.FromCanceled <object[]>(cancellationToken));
     }
     return(batchableCache.GetManyAsync(keys, timestamp, cancellationToken));
 }
 /// <summary>
 /// Attempt to cache objects, after loading them from the database.
 /// </summary>
 /// <param name="cache">The cache concurrency strategy.</param>
 /// <param name="keys">The keys (id) of the objects to put in the Cache.</param>
 /// <param name="values">The objects to put in the cache.</param>
 /// <param name="timestamp">A timestamp prior to the transaction start time.</param>
 /// <param name="versions">The version numbers of the objects we are putting.</param>
 /// <param name="versionComparers">The comparers to be used to compare version numbers</param>
 /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param>
 /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
 /// <returns><see langword="true" /> if the objects were successfully cached.</returns>
 /// <exception cref="CacheException"></exception>
 public static Task <bool[]> PutManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp,
                                          object[] versions, IComparer[] versionComparers, bool[] minimalPuts, CancellationToken cancellationToken)
 {
     if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache))
     {
         throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching");
     }
     if (cancellationToken.IsCancellationRequested)
     {
         return(Task.FromCanceled <bool[]>(cancellationToken));
     }
     return(batchableCache.PutManyAsync(keys, values, timestamp, versions, versionComparers, minimalPuts, cancellationToken));
 }
Пример #20
0
        // 6.0 TODO: remove
        internal static CacheBase GetCacheBase(this ICacheConcurrencyStrategy cache)
        {
            if (cache is IBatchableCacheConcurrencyStrategy batchableCache)
            {
                return(batchableCache.Cache);
            }
            var concreteCache = cache.Cache;

            if (concreteCache == null)
            {
                return(null);
            }
            return(concreteCache as CacheBase ?? new ObsoleteCacheWrapper(concreteCache));
        }
		public static ICollectionPersister CreateCollectionPersister(Mapping.Collection model, ICacheConcurrencyStrategy cache,
		                                                             ISessionFactoryImplementor factory)
		{
			System.Type persisterClass = model.CollectionPersisterClass;
			if (persisterClass == null)
			{
				// default behaviour
				return model.IsOneToMany ?
				       (ICollectionPersister) new OneToManyPersister(model, cache, factory) :
				       (ICollectionPersister) new BasicCollectionPersister(model, cache, factory);
			}
			else
			{
				return Create(persisterClass, model, cache, factory);
			}
		}
        /// <summary>
        /// Attempt to cache objects, after loading them from the database.
        /// </summary>
        /// <param name="cache">The cache concurrency strategy.</param>
        /// <param name="keys">The keys (id) of the objects to put in the Cache.</param>
        /// <param name="values">The objects to put in the cache.</param>
        /// <param name="timestamp">A timestamp prior to the transaction start time.</param>
        /// <param name="versions">The version numbers of the objects we are putting.</param>
        /// <param name="versionComparers">The comparers to be used to compare version numbers</param>
        /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param>
        /// <returns><see langword="true" /> if the objects were successfully cached.</returns>
        /// <exception cref="CacheException"></exception>
        public static bool[] PutMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp,
                                     object[] versions, IComparer[] versionComparers, bool[] minimalPuts)
        {
            if (cache is IBatchableCacheConcurrencyStrategy batchableCache)
            {
                return(batchableCache.PutMany(keys, values, timestamp, versions, versionComparers, minimalPuts));
            }

            var result = new bool[keys.Length];

            for (var i = 0; i < keys.Length; i++)
            {
                result[i] = cache.Put(keys[i], values[i], timestamp, versions[i], versionComparers[i], minimalPuts[i]);
            }

            return(result);
        }
		/// <summary>
		/// Creates a built in Entity Persister or a custom Persister.
		/// </summary>
		public static IEntityPersister CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache,
		                                                    ISessionFactoryImplementor factory, IMapping cfg)
		{
			System.Type persisterClass = model.ClassPersisterClass;

			if (persisterClass == null || persisterClass == typeof(SingleTableEntityPersister))
			{
				return new SingleTableEntityPersister(model, cache, factory, cfg);
			}
			else if (persisterClass == typeof(JoinedSubclassEntityPersister))
			{
				return new JoinedSubclassEntityPersister(model, cache, factory, cfg);
			}
			else
			{
				return Create(persisterClass, model, cache, factory, cfg);
			}
		}
        /// <summary>
        /// Attempt to cache objects, after loading them from the database.
        /// </summary>
        /// <param name="cache">The cache concurrency strategy.</param>
        /// <param name="keys">The keys (id) of the objects to put in the Cache.</param>
        /// <param name="values">The objects to put in the cache.</param>
        /// <param name="timestamp">A timestamp prior to the transaction start time.</param>
        /// <param name="versions">The version numbers of the objects we are putting.</param>
        /// <param name="versionComparers">The comparers to be used to compare version numbers</param>
        /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param>
        /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
        /// <returns><see langword="true" /> if the objects were successfully cached.</returns>
        /// <exception cref="CacheException"></exception>
        public static async Task <bool[]> PutManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp,
                                                       object[] versions, IComparer[] versionComparers, bool[] minimalPuts, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (cache is IBatchableCacheConcurrencyStrategy batchableCache)
            {
                return(await(batchableCache.PutManyAsync(keys, values, timestamp, versions, versionComparers, minimalPuts, cancellationToken)).ConfigureAwait(false));
            }

            var result = new bool[keys.Length];

            for (var i = 0; i < keys.Length; i++)
            {
                result[i] = await(cache.PutAsync(keys[i], values[i], timestamp, versions[i], versionComparers[i], minimalPuts[i], cancellationToken)).ConfigureAwait(false);
            }

            return(result);
        }
 /// <summary>
 /// Attempt to retrieve multiple objects from the Cache
 /// </summary>
 /// <param name="cache">The cache concurrency strategy.</param>
 /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param>
 /// <param name="timestamp">A timestamp prior to the transaction start time</param>
 /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
 /// <returns>An array of cached objects or <see langword="null" /></returns>
 /// <exception cref="CacheException"></exception>
 public static Task <object[]> GetManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp, CancellationToken cancellationToken)
 {
     if (cancellationToken.IsCancellationRequested)
     {
         return(Task.FromCanceled <object[]>(cancellationToken));
     }
     try
     {
         // PreferMultipleGet yields false if !IBatchableCacheConcurrencyStrategy, no GetMany call should be done
         // in such case.
         return(ReflectHelper
                .CastOrThrow <IBatchableCacheConcurrencyStrategy>(cache, "batching")
                .GetManyAsync(keys, timestamp, cancellationToken));
     }
     catch (System.Exception ex)
     {
         return(Task.FromException <object[]>(ex));
     }
 }
Пример #26
0
        /// <summary>
        /// Creates a built in Entity Persister or a custom Persister.
        /// </summary>
        public static IEntityPersister CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache,
                                                            ISessionFactoryImplementor factory, IMapping cfg)
        {
            System.Type persisterClass = model.EntityPersisterClass;

            if (persisterClass == null || persisterClass == typeof(SingleTableEntityPersister))
            {
                return(new SingleTableEntityPersister(model, cache, factory, cfg));
            }
            else if (persisterClass == typeof(JoinedSubclassEntityPersister))
            {
                return(new JoinedSubclassEntityPersister(model, cache, factory, cfg));
            }
            else if (persisterClass == typeof(UnionSubclassEntityPersister))
            {
                return(new UnionSubclassEntityPersister(model, cache, factory, cfg));
            }
            else
            {
                return(Create(persisterClass, model, cache, factory, cfg));
            }
        }
Пример #27
0
        /// <summary>
        /// Creates an <see cref="ICacheConcurrencyStrategy"/> from the parameters.
        /// </summary>
        /// <param name="usage">The name of the strategy that <see cref="ICacheProvider"/> should use for the class.</param>
        /// <param name="name">The name of the class the strategy is being created for.</param>
        /// <param name="mutable"><c>true</c> if the object being stored in the cache is mutable.</param>
        /// <returns>An <see cref="ICacheConcurrencyStrategy"/> to use for this object in the <see cref="ICache"/>.</returns>
        // was private in h2.1
        public static ICacheConcurrencyStrategy CreateCache(string usage, string name, bool mutable)
        {
            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format("cache for: {0} usage strategy: {1}", name, usage));
            }

            ICacheConcurrencyStrategy ccs = null;

            switch (usage)
            {
            case CacheFactory.ReadOnly:
                if (mutable)
                {
                    log.Warn("read-only cache configured for mutable: " + name);
                }
                ccs = new ReadOnlyCache();
                break;

            case CacheFactory.ReadWrite:
                ccs = new ReadWriteCache();
                break;

            case CacheFactory.NonstrictReadWrite:
                ccs = new NonstrictReadWriteCache();
                break;

            //case CacheFactory.Transactional:
            //	ccs = new TransactionalCache();
            //	break;
            default:
                throw new MappingException("cache usage attribute should be read-write, read-only, nonstrict-read-write, or transactional");
            }

            return(ccs);
        }
        /// <summary>
        /// Creates a specific Persister - could be a built in or custom persister.
        /// </summary>
        public static IEntityPersister Create(System.Type persisterClass, PersistentClass model,
                                              ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory,
                                              IMapping cfg)
        {
            ConstructorInfo pc;

            try
            {
                pc = persisterClass.GetConstructor(PersisterConstructorArgs);
            }
            catch (Exception e)
            {
                throw new MappingException("Could not get constructor for " + persisterClass.Name, e);
            }

            try
            {
                return((IEntityPersister)pc.Invoke(new object[] { model, cache, factory, cfg }));
            }
            catch (TargetInvocationException tie)
            {
                Exception e = tie.InnerException;
                if (e is HibernateException)
                {
                    throw ReflectHelper.UnwrapTargetInvocationException(tie);
                }
                else
                {
                    throw new MappingException("Could not instantiate persister " + persisterClass.Name, e);
                }
            }
            catch (Exception e)
            {
                throw new MappingException("Could not instantiate persister " + persisterClass.Name, e);
            }
        }
		public MyCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) : base(collection, cache, cfg, factory) {}
		/// <summary>
		/// Constructs the NormalizedEntityPerister for the PersistentClass.
		/// </summary>
		/// <param name="persistentClass">The PersistentClass to create the EntityPersister for.</param>
		/// <param name="cache">The configured <see cref="ICacheConcurrencyStrategy" />.</param>
		/// <param name="factory">The SessionFactory that this EntityPersister will be stored in.</param>
		/// <param name="mapping">The mapping used to retrieve type information.</param>
		public JoinedSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
											 ISessionFactoryImplementor factory, IMapping mapping)
			: base(persistentClass, cache, factory)
		{
			#region DISCRIMINATOR

			if (persistentClass.IsPolymorphic)
			{
				try
				{
					discriminatorValue = persistentClass.SubclassId;
					discriminatorSQLString = discriminatorValue.ToString();
				}
				catch (Exception e)
				{
					throw new MappingException("Could not format discriminator value to SQL string", e);
				}
			}
			else
			{
				discriminatorValue = null;
				discriminatorSQLString = null;
			}

			if (OptimisticLockMode > Versioning.OptimisticLock.Version)
				throw new MappingException(string.Format("optimistic-lock=all|dirty not supported for joined-subclass mappings [{0}]", EntityName));

			#endregion

			#region MULTITABLES
			int idColumnSpan = IdentifierColumnSpan;

			List<string> tables = new List<string>();
			List<string[]> keyColumns = new List<string[]>();
			List<bool> cascadeDeletes = new List<bool>();
			IEnumerator<IKeyValue> kiter = persistentClass.KeyClosureIterator.GetEnumerator();
			foreach (Table tab in persistentClass.TableClosureIterator)
			{
				kiter.MoveNext();
				IKeyValue key = kiter.Current;
				string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				tables.Add(tabname);

				List<string> keyCols = new List<string>(idColumnSpan);
				IEnumerable<Column> enumerableKCols = new SafetyEnumerable<Column>(key.ColumnIterator);
				foreach (Column kcol in enumerableKCols)
					keyCols.Add(kcol.GetQuotedName(factory.Dialect));

				keyColumns.Add(keyCols.ToArray());
				cascadeDeletes.Add(key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete);				
			}
			naturalOrderTableNames = tables.ToArray();
			naturalOrderTableKeyColumns = keyColumns.ToArray();
			naturalOrderCascadeDeleteEnabled = cascadeDeletes.ToArray();

			List<string> subtables = new List<string>();
			List<bool> isConcretes = new List<bool>();
			keyColumns = new List<string[]>();
			foreach (Table tab in persistentClass.SubclassTableClosureIterator)
			{
				isConcretes.Add(persistentClass.IsClassOrSuperclassTable(tab));
				string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				subtables.Add(tabname);
				List<string> key = new List<string>(idColumnSpan);
				foreach (Column column in tab.PrimaryKey.ColumnIterator)
					key.Add(column.GetQuotedName(factory.Dialect));

				keyColumns.Add(key.ToArray());				
			}
			subclassTableNameClosure = subtables.ToArray();
			subclassTableKeyColumnClosure = keyColumns.ToArray();
			isClassOrSuperclassTable = isConcretes.ToArray();

			constraintOrderedTableNames = new string[subclassTableNameClosure.Length];
			constraintOrderedKeyColumnNames = new string[subclassTableNameClosure.Length][];
			int currentPosition = 0;
			for (int i = subclassTableNameClosure.Length - 1; i >= 0; i--, currentPosition++)
			{
				constraintOrderedTableNames[currentPosition] = subclassTableNameClosure[i];
				constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i];
			}

			tableSpan = naturalOrderTableNames.Length;
			tableNames = Reverse(naturalOrderTableNames);
			tableKeyColumns = Reverse(naturalOrderTableKeyColumns);
			Reverse(subclassTableNameClosure, tableSpan);
			Reverse(subclassTableKeyColumnClosure, tableSpan);

			spaces = ArrayHelper.Join(tableNames, persistentClass.SynchronizedTables.ToArray());

			// Custom sql
			customSQLInsert = new SqlString[tableSpan];
			customSQLUpdate = new SqlString[tableSpan];
			customSQLDelete = new SqlString[tableSpan];
			insertCallable = new bool[tableSpan];
			updateCallable = new bool[tableSpan];
			deleteCallable = new bool[tableSpan];
			insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
			updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
			deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];

			PersistentClass pc = persistentClass;
			int jk = tableSpan - 1;
			while (pc != null)
			{
				customSQLInsert[jk] = pc.CustomSQLInsert;
				insertCallable[jk] = customSQLInsert[jk] != null && pc.IsCustomInsertCallable;
				insertResultCheckStyles[jk] = pc.CustomSQLInsertCheckStyle
											  ??
											  ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[jk], insertCallable[jk]);
				customSQLUpdate[jk] = pc.CustomSQLUpdate;
				updateCallable[jk] = customSQLUpdate[jk] != null && pc.IsCustomUpdateCallable;
				updateResultCheckStyles[jk] = pc.CustomSQLUpdateCheckStyle
											  ??
											  ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[jk], updateCallable[jk]);
				customSQLDelete[jk] = pc.CustomSQLDelete;
				deleteCallable[jk] = customSQLDelete[jk] != null && pc.IsCustomDeleteCallable;
				deleteResultCheckStyles[jk] = pc.CustomSQLDeleteCheckStyle
											  ??
											  ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[jk], deleteCallable[jk]);
				jk--;
				pc = pc.Superclass;
			}
			if (jk != -1)
			{
				throw new AssertionFailure("Tablespan does not match height of joined-subclass hierarchy.");
			}

			#endregion

			#region PROPERTIES

			int hydrateSpan = PropertySpan;
			naturalOrderPropertyTableNumbers = new int[hydrateSpan];
			propertyTableNumbers = new int[hydrateSpan];
			int i2 = 0;
			foreach (Property prop in persistentClass.PropertyClosureIterator)
			{
				string tabname = prop.Value.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				propertyTableNumbers[i2] = GetTableId(tabname, tableNames);
				naturalOrderPropertyTableNumbers[i2] = GetTableId(tabname, naturalOrderTableNames);
				i2++;
			}

			// subclass closure properties
			List<int> columnTableNumbers = new List<int>();
			List<int> formulaTableNumbers = new List<int>();
			List<int> propTableNumbers = new List<int>();
			foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
			{
				Table tab = prop.Value.Table;
				string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				int tabnum = GetTableId(tabname, subclassTableNameClosure);
				propTableNumbers.Add(tabnum);

				foreach (ISelectable thing in prop.ColumnIterator)
				{
					if (thing.IsFormula)
						formulaTableNumbers.Add(tabnum);
					else
						columnTableNumbers.Add(tabnum);
				}
			}

			subclassColumnTableNumberClosure = columnTableNumbers.ToArray();
			subclassPropertyTableNumberClosure = propTableNumbers.ToArray();
			subclassFormulaTableNumberClosure = formulaTableNumbers.ToArray();
			#endregion

			#region SUBCLASSES

			int subclassSpan = persistentClass.SubclassSpan + 1;
			subclassClosure = new string[subclassSpan];
			subclassClosure[subclassSpan - 1] = EntityName;
			if (persistentClass.IsPolymorphic)
			{
				subclassesByDiscriminatorValue[discriminatorValue] = EntityName;
				discriminatorValues = new string[subclassSpan];
				discriminatorValues[subclassSpan - 1] = discriminatorSQLString;
				notNullColumnTableNumbers = new int[subclassSpan];
				int id =
					GetTableId(
						persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
															   factory.Settings.DefaultSchemaName), subclassTableNameClosure);
				notNullColumnTableNumbers[subclassSpan - 1] = id;
				notNullColumnNames = new string[subclassSpan];
				notNullColumnNames[subclassSpan - 1] = subclassTableKeyColumnClosure[id][0]; 
				//( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
			}
			else
			{
				discriminatorValues = null;
				notNullColumnTableNumbers = null;
				notNullColumnNames = null;
			}

			int k2 = 0;
			foreach (Subclass sc in persistentClass.SubclassIterator)
			{
				subclassClosure[k2] = sc.EntityName;
				try
				{
					if (persistentClass.IsPolymorphic)
					{
						// we now use subclass ids that are consistent across all
						// persisters for a class hierarchy, so that the use of 
						// "foo.class = Bar" works in HQL
						int subclassId = sc.SubclassId; //new Integer(k+1);
						subclassesByDiscriminatorValue[subclassId] = sc.EntityName;
						discriminatorValues[k2] = subclassId.ToString();
						int id =
							GetTableId(
								sc.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
														  factory.Settings.DefaultSchemaName), subclassTableNameClosure);
						notNullColumnTableNumbers[k2] = id;
						notNullColumnNames[k2] = subclassTableKeyColumnClosure[id][0]; 
						//( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
					}
				}
				catch (Exception e)
				{
					throw new MappingException("Error parsing discriminator value", e);
				}
				k2++;				
			}

			#endregion

			InitLockers();

			InitSubclassPropertyAliasesMap(persistentClass);

			PostConstruct(mapping);
		}
Пример #31
0
 public BasicCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory)
     : base(collection, cache, cfg, factory)
 {
 }
		public AbstractCollectionPersister( Mapping.Collection collection, ISessionFactoryImplementor factory )
		{
			this.factory = factory;
			dialect = factory.Dialect;
			//sqlExceptionConverter = factory.SQLExceptionConverter;
			collectionType = collection.CollectionType;
			role = collection.Role;
			ownerClass = collection.OwnerClass;
			Alias alias = new Alias( "__" );

			sqlOrderByString = collection.OrderBy;
			hasOrder = sqlOrderByString != null;
			sqlOrderByStringTemplate = hasOrder ? Template.RenderOrderByStringTemplate( sqlOrderByString, dialect ) : null;

			sqlWhereString = collection.Where;
			hasWhere = sqlWhereString != null;
			sqlWhereStringTemplate = hasWhere ? Template.RenderWhereStringTemplate( sqlWhereString, dialect ) : null;

			hasOrphanDelete = collection.OrphanDelete;

			batchSize = collection.BatchSize;

			cache = collection.Cache;

			keyType = collection.Key.Type;
			int keySpan = collection.Key.ColumnSpan;
			keyColumnNames = new string[keySpan];
			string[ ] keyAliases = new string[keySpan];
			int k = 0;
			foreach( Column col in collection.Key.ColumnCollection )
			{
				keyColumnNames[ k ] = col.GetQuotedName( dialect );
				keyAliases[ k ] = col.Alias( dialect );
				k++;
			}
			keyColumnAliases = alias.ToAliasStrings( keyAliases, dialect );
			//unquotedKeyColumnNames = StringHelper.Unquote( keyColumnAliases );
			ISet distinctColumns = new HashedSet();
			CheckColumnDuplication( distinctColumns, collection.Key.ColumnCollection );

			//isSet = collection.IsSet;
			//isSorted = collection.IsSorted;
			primitiveArray = collection.IsPrimitiveArray;
			array = collection.IsArray;

			IValue element = collection.Element;
			int elementSpan = element.ColumnSpan;
			ICollection iter = element.ColumnCollection;
			Table table = collection.CollectionTable;
			enableJoinedFetch = element.OuterJoinFetchSetting;
			elementType = element.Type;

			if( !collection.IsOneToMany )
			{
				CheckColumnDuplication( distinctColumns, element.ColumnCollection );
			}

			if( elementType.IsEntityType )
			{
				elementPersister = factory.GetPersister( ( ( EntityType ) elementType ).AssociatedClass );
			}
			else
			{
				elementPersister = null;
			}

			qualifiedTableName = table.GetQualifiedName( dialect, factory.DefaultSchema );
			string[ ] aliases = new string[elementSpan];
			elementColumnNames = new string[elementSpan];
			int j = 0;
			foreach( Column col in iter )
			{
				elementColumnNames[ j ] = col.GetQuotedName( dialect );
				aliases[ j ] = col.Alias( dialect );
				j++;
			}

			elementColumnAliases = alias.ToAliasStrings( aliases, dialect );

			IType selectColumns;
			string[ ] selectType;

			hasIndex = collection.IsIndexed;

			if( hasIndex )
			{
				IndexedCollection indexedCollection = ( IndexedCollection ) collection;

				indexType = indexedCollection.Index.Type;
				int indexSpan = indexedCollection.Index.ColumnSpan;
				indexColumnNames = new string[indexSpan];

				string[ ] indexAliases = new string[indexSpan];
				int i = 0;
				foreach( Column indexCol in indexedCollection.Index.ColumnCollection )
				{
					indexAliases[ i ] = indexCol.Alias( dialect );
					indexColumnNames[ i ] = indexCol.GetQuotedName( dialect );
					i++;
				}
				selectType = indexColumnNames;
				selectColumns = indexType;
				indexColumnAliases = alias.ToAliasStrings( indexAliases, dialect );
				CheckColumnDuplication( distinctColumns, indexedCollection.Index.ColumnCollection );
			}
			else
			{
				indexType = null;
				indexColumnNames = null;
				indexColumnAliases = null;
				selectType = elementColumnNames;
				selectColumns = elementType;
			}

			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.ColumnCollection )
				{
					col = column;
					break;
				}

				identifierColumnName = col.GetQuotedName( dialect );
				selectType = new string[ ] {identifierColumnName};
				selectColumns = identifierType;
				identifierColumnAlias = alias.ToAliasString( col.Alias( dialect ), dialect );
				unquotedIdentifierColumnName = identifierColumnAlias;
				identifierGenerator = idColl.Identifier.CreateIdentifierGenerator( dialect );
				CheckColumnDuplication( distinctColumns, idColl.Identifier.ColumnCollection );
			}
			else
			{
				identifierType = null;
				identifierColumnName = null;
				identifierColumnAlias = null;
				unquotedIdentifierColumnName = null;
				identifierGenerator = null;
			}

			rowSelectColumnNames = selectType;
			rowSelectType = selectColumns;

			sqlDeleteString = GenerateDeleteString();
			sqlInsertRowString = GenerateInsertRowString();
			sqlUpdateRowString = GenerateUpdateRowString();
			sqlDeleteRowString = GenerateDeleteRowString();
			isLazy = collection.IsLazy;

			isInverse = collection.IsInverse;

			if( collection.IsArray )
			{
				elementClass = ( ( Array ) collection ).ElementClass;
			}
			else
			{
				// for non-arrays, we don't need to know the element class
				elementClass = null;
			}

			initializer = CreateCollectionInitializer( factory );

			if( elementType.IsComponentType )
			{
				elementPropertyMapping = new CompositeElementPropertyMapping( elementColumnNames, ( IAbstractComponentType ) elementType, factory );
			}
			else if( !elementType.IsEntityType )
			{
				elementPropertyMapping = new ElementPropertyMapping( elementColumnNames, elementType );
			}
			else
			{
				IClassPersister persister = factory.GetPersister( ( ( EntityType ) elementType ).AssociatedClass );
				// Not all classpersisters implement IPropertyMapping!
				if( persister is IPropertyMapping )
				{
					elementPropertyMapping = ( IPropertyMapping ) persister;
				}
				else
				{
					elementPropertyMapping = new ElementPropertyMapping( elementColumnNames, elementType );
				}
			}
		}
Пример #33
0
 public CustomPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory,
                        IMapping mapping)
 {
     this.factory = factory;
 }
		public UnionSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, 
			ISessionFactoryImplementor factory, IMapping mapping):base(persistentClass, cache, factory)
		{
			if (IdentifierGenerator is IdentityGenerator)
			{
				throw new MappingException("Cannot use identity column key generation with <union-subclass> mapping for: " + EntityName);
			}

			// TABLE

			tableName =
				persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
				                                       factory.Settings.DefaultSchemaName);

			#region Custom SQL

			SqlString sql;
			bool callable;
			ExecuteUpdateResultCheckStyle checkStyle;

			sql = persistentClass.CustomSQLInsert;
			callable = sql != null && persistentClass.IsCustomInsertCallable;
			checkStyle = sql == null
			             	? ExecuteUpdateResultCheckStyle.Count
			             	: (persistentClass.CustomSQLInsertCheckStyle
			             	   ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable));
			customSQLInsert = new SqlString[] { sql };
			insertCallable = new bool[] { callable };
			insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle };

			sql = persistentClass.CustomSQLUpdate;
			callable = sql != null && persistentClass.IsCustomUpdateCallable;
			checkStyle = sql == null
			             	? ExecuteUpdateResultCheckStyle.Count
			             	: (persistentClass.CustomSQLUpdateCheckStyle
			             	   ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable));
			customSQLUpdate = new SqlString[] { sql };
			updateCallable = new bool[] { callable };
			updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle };

			sql = persistentClass.CustomSQLDelete;
			callable = sql != null && persistentClass.IsCustomDeleteCallable;
			checkStyle = sql == null
			             	? ExecuteUpdateResultCheckStyle.Count
			             	: (persistentClass.CustomSQLDeleteCheckStyle
			             	   ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable));
			customSQLDelete = new SqlString[] { sql };
			deleteCallable = new bool[] { callable };
			deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle };

			#endregion

			discriminatorValue = persistentClass.SubclassId;
			discriminatorSQLValue = persistentClass.SubclassId.ToString();

			#region PROPERTIES

			int subclassSpan = persistentClass.SubclassSpan + 1;
			subclassClosure = new string[subclassSpan];
			subclassClosure[0] = EntityName;

			#endregion

			#region SUBCLASSES

			subclassByDiscriminatorValue[persistentClass.SubclassId] = persistentClass.EntityName;
			if (persistentClass.IsPolymorphic)
			{
				int k = 1;
				foreach (Subclass sc in persistentClass.SubclassIterator)
				{
					subclassClosure[k++] = sc.EntityName;
					subclassByDiscriminatorValue[sc.SubclassId] = sc.EntityName;
				}
			}

			#endregion

			#region SPACES
			//TODO: i'm not sure, but perhaps we should exclude abstract denormalized tables?

			int spacesSize = 1 + persistentClass.SynchronizedTables.Count;
			spaces = new string[spacesSize];
			spaces[0] = tableName;
			IEnumerator<string> iSyncTab = persistentClass.SynchronizedTables.GetEnumerator();
			for (int i = 1; i < spacesSize; i++)
			{
				iSyncTab.MoveNext();
				spaces[i] = iSyncTab.Current;
			}

			HashedSet<string> subclassTables = new HashedSet<string>();
			foreach (Table table in persistentClass.SubclassTableClosureIterator)
			{
				subclassTables.Add(
					table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName));
			}
			subclassSpaces = new string[subclassTables.Count];
			subclassTables.CopyTo(subclassSpaces, 0);

			subquery = GenerateSubquery(persistentClass, mapping);

			if (IsMultiTable)
			{
				int idColumnSpan = IdentifierColumnSpan;
				List<string> tableNames = new List<string>();
				List<string[]> keyColumns = new List<string[]>();
				if (!IsAbstract)
				{
					tableNames.Add(tableName);
					keyColumns.Add(IdentifierColumnNames);
				}
				foreach (Table tab in persistentClass.SubclassTableClosureIterator)
				{
					if (!tab.IsAbstractUnionTable)
					{
						string _tableName =
							tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
						tableNames.Add(_tableName);

						List<string> key = new List<string>(idColumnSpan);
						foreach (Column column in tab.PrimaryKey.ColumnIterator)
							key.Add(column.GetQuotedName(factory.Dialect));

						keyColumns.Add(key.ToArray());
					}					
				}

				constraintOrderedTableNames = tableNames.ToArray();
				constraintOrderedKeyColumnNames = keyColumns.ToArray();
			}
			else
			{
				constraintOrderedTableNames = new string[] { tableName };
				constraintOrderedKeyColumnNames = new string[][] { IdentifierColumnNames };
			}
			#endregion

			InitLockers();

			InitSubclassPropertyAliasesMap(persistentClass);

			PostConstruct(mapping);
		}
Пример #35
0
 public CachePutBatch(ISessionImplementor session, ICacheConcurrencyStrategy cacheConcurrencyStrategy) : base(session, cacheConcurrencyStrategy)
 {
 }
Пример #36
0
        public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
        {
            Init();
            log.Info("building session factory");

            properties          = new Dictionary <string, string>(cfg.Properties);
            interceptor         = cfg.Interceptor;
            this.settings       = settings;
            sqlFunctionRegistry = new SQLFunctionRegistry(settings.Dialect, cfg.SqlFunctions);
            eventListeners      = listeners;
            filters             = new Dictionary <string, FilterDefinition>(cfg.FilterDefinitions);
            if (log.IsDebugEnabled)
            {
                log.Debug("Session factory constructed with filter configurations : " + CollectionPrinter.ToString(filters));
            }

            if (log.IsDebugEnabled)
            {
                log.Debug("instantiating session factory with properties: " + CollectionPrinter.ToString(properties));
            }

            try
            {
                if (settings.IsKeywordsImportEnabled)
                {
                    SchemaMetadataUpdater.Update(this);
                }
                if (settings.IsAutoQuoteEnabled)
                {
                    SchemaMetadataUpdater.QuoteTableAndColumns(cfg);
                }
            }
            catch (NotSupportedException)
            {
                // Ignore if the Dialect does not provide DataBaseSchema
            }

            #region Caches
            settings.CacheProvider.Start(properties);
            #endregion

            #region Generators
            identifierGenerators = new Dictionary <string, IIdentifierGenerator>();
            foreach (PersistentClass model in cfg.ClassMappings)
            {
                if (!model.IsInherited)
                {
                    IIdentifierGenerator generator =
                        model.Identifier.CreateIdentifierGenerator(settings.Dialect, settings.DefaultCatalogName,
                                                                   settings.DefaultSchemaName, (RootClass)model);

                    identifierGenerators[model.EntityName] = generator;
                }
            }
            #endregion

            #region Persisters

            Dictionary <string, ICacheConcurrencyStrategy> caches = new Dictionary <string, ICacheConcurrencyStrategy>();
            entityPersisters        = new Dictionary <string, IEntityPersister>();
            implementorToEntityName = new Dictionary <System.Type, string>();

            Dictionary <string, IClassMetadata> classMeta = new Dictionary <string, IClassMetadata>();

            foreach (PersistentClass model in cfg.ClassMappings)
            {
                model.PrepareTemporaryTables(mapping, settings.Dialect);
                string cacheRegion = model.RootClazz.CacheRegionName;
                ICacheConcurrencyStrategy cache;
                if (!caches.TryGetValue(cacheRegion, out cache))
                {
                    cache =
                        CacheFactory.CreateCache(model.CacheConcurrencyStrategy, cacheRegion, model.IsMutable, settings, properties);
                    if (cache != null)
                    {
                        caches.Add(cacheRegion, cache);
                        allCacheRegions.Add(cache.RegionName, cache.Cache);
                    }
                }
                IEntityPersister cp = PersisterFactory.CreateClassPersister(model, cache, this, mapping);
                entityPersisters[model.EntityName] = cp;
                classMeta[model.EntityName]        = cp.ClassMetadata;

                if (model.HasPocoRepresentation)
                {
                    implementorToEntityName[model.MappedClass] = model.EntityName;
                }
            }
            classMetadata = new UnmodifiableDictionary <string, IClassMetadata>(classMeta);

            Dictionary <string, ISet <string> > tmpEntityToCollectionRoleMap = new Dictionary <string, ISet <string> >();
            collectionPersisters = new Dictionary <string, ICollectionPersister>();
            foreach (Mapping.Collection model in cfg.CollectionMappings)
            {
                ICacheConcurrencyStrategy cache =
                    CacheFactory.CreateCache(model.CacheConcurrencyStrategy, model.CacheRegionName, model.Owner.IsMutable, settings,
                                             properties);
                if (cache != null)
                {
                    allCacheRegions[cache.RegionName] = cache.Cache;
                }
                ICollectionPersister persister = PersisterFactory.CreateCollectionPersister(cfg, model, cache, this);
                collectionPersisters[model.Role] = persister;
                IType indexType = persister.IndexType;
                if (indexType != null && indexType.IsAssociationType && !indexType.IsAnyType)
                {
                    string        entityName = ((IAssociationType)indexType).GetAssociatedEntityName(this);
                    ISet <string> roles;
                    if (!tmpEntityToCollectionRoleMap.TryGetValue(entityName, out roles))
                    {
                        roles = new HashSet <string>();
                        tmpEntityToCollectionRoleMap[entityName] = roles;
                    }
                    roles.Add(persister.Role);
                }
                IType elementType = persister.ElementType;
                if (elementType.IsAssociationType && !elementType.IsAnyType)
                {
                    string        entityName = ((IAssociationType)elementType).GetAssociatedEntityName(this);
                    ISet <string> roles;
                    if (!tmpEntityToCollectionRoleMap.TryGetValue(entityName, out roles))
                    {
                        roles = new HashSet <string>();
                        tmpEntityToCollectionRoleMap[entityName] = roles;
                    }
                    roles.Add(persister.Role);
                }
            }
            Dictionary <string, ICollectionMetadata> tmpcollectionMetadata = new Dictionary <string, ICollectionMetadata>(collectionPersisters.Count);
            foreach (KeyValuePair <string, ICollectionPersister> collectionPersister in collectionPersisters)
            {
                tmpcollectionMetadata.Add(collectionPersister.Key, collectionPersister.Value.CollectionMetadata);
            }
            collectionMetadata = new UnmodifiableDictionary <string, ICollectionMetadata>(tmpcollectionMetadata);
            collectionRolesByEntityParticipant = new UnmodifiableDictionary <string, ISet <string> >(tmpEntityToCollectionRoleMap);
            #endregion

            #region Named Queries
            namedQueries         = new Dictionary <string, NamedQueryDefinition>(cfg.NamedQueries);
            namedSqlQueries      = new Dictionary <string, NamedSQLQueryDefinition>(cfg.NamedSQLQueries);
            sqlResultSetMappings = new Dictionary <string, ResultSetMappingDefinition>(cfg.SqlResultSetMappings);
            #endregion

            imports = new Dictionary <string, string>(cfg.Imports);

            #region after *all* persisters and named queries are registered
            foreach (IEntityPersister persister in entityPersisters.Values)
            {
                persister.PostInstantiate();
            }
            foreach (ICollectionPersister persister in collectionPersisters.Values)
            {
                persister.PostInstantiate();
            }
            #endregion

            #region Serialization info

            name = settings.SessionFactoryName;
            try
            {
                uuid = (string)UuidGenerator.Generate(null, null);
            }
            catch (Exception)
            {
                throw new AssertionFailure("Could not generate UUID");
            }

            SessionFactoryObjectFactory.AddInstance(uuid, name, this, properties);

            #endregion

            log.Debug("Instantiated session factory");

            #region Schema management
            if (settings.IsAutoCreateSchema)
            {
                new SchemaExport(cfg).Create(false, true);
            }

            if (settings.IsAutoUpdateSchema)
            {
                new SchemaUpdate(cfg).Execute(false, true);
            }
            if (settings.IsAutoValidateSchema)
            {
                new SchemaValidator(cfg, settings).Validate();
            }
            if (settings.IsAutoDropSchema)
            {
                schemaExport = new SchemaExport(cfg);
            }
            #endregion

            #region Obtaining TransactionManager
            // not ported yet
            #endregion

            currentSessionContext = BuildCurrentSessionContext();

            if (settings.IsQueryCacheEnabled)
            {
                updateTimestampsCache = new UpdateTimestampsCache(settings, properties);
                queryCache            = settings.QueryCacheFactory.GetQueryCache(null, updateTimestampsCache, settings, properties);
                queryCaches           = new ThreadSafeDictionary <string, IQueryCache>(new Dictionary <string, IQueryCache>());
            }
            else
            {
                updateTimestampsCache = null;
                queryCache            = null;
                queryCaches           = null;
            }

            #region Checking for named queries
            if (settings.IsNamedQueryStartupCheckingEnabled)
            {
                IDictionary <string, HibernateException> errors = CheckNamedQueries();
                if (errors.Count > 0)
                {
                    StringBuilder failingQueries = new StringBuilder("Errors in named queries: ");
                    foreach (KeyValuePair <string, HibernateException> pair in errors)
                    {
                        failingQueries.Append('{').Append(pair.Key).Append('}');
                        log.Error("Error in named query: " + pair.Key, pair.Value);
                    }
                    throw new HibernateException(failingQueries.ToString());
                }
            }
            #endregion

            Statistics.IsStatisticsEnabled = settings.IsStatisticsEnabled;

            // EntityNotFoundDelegate
            IEntityNotFoundDelegate enfd = cfg.EntityNotFoundDelegate;
            if (enfd == null)
            {
                enfd = new DefaultEntityNotFoundDelegate();
            }
            entityNotFoundDelegate = enfd;
        }
        /// <summary>
        /// Constructs the NormalizedEntityPerister for the PersistentClass.
        /// </summary>
        /// <param name="persistentClass">The PersistentClass to create the EntityPersister for.</param>
        /// <param name="cache">The configured <see cref="ICacheConcurrencyStrategy" />.</param>
        /// <param name="factory">The SessionFactory that this EntityPersister will be stored in.</param>
        /// <param name="mapping">The mapping used to retrieve type information.</param>
        public JoinedSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
                                             ISessionFactoryImplementor factory, IMapping mapping)
            : base(persistentClass, cache, factory)
        {
            #region DISCRIMINATOR

            if (persistentClass.IsPolymorphic)
            {
                try
                {
                    discriminatorValue     = persistentClass.SubclassId;
                    discriminatorSQLString = discriminatorValue.ToString();
                }
                catch (Exception e)
                {
                    throw new MappingException("Could not format discriminator value to SQL string", e);
                }
            }
            else
            {
                discriminatorValue     = null;
                discriminatorSQLString = null;
            }

            if (OptimisticLockMode > Versioning.OptimisticLock.Version)
            {
                throw new MappingException(string.Format("optimistic-lock=all|dirty not supported for joined-subclass mappings [{0}]", EntityName));
            }

            #endregion

            #region MULTITABLES
            int idColumnSpan = IdentifierColumnSpan;

            List <string>   tables         = new List <string>();
            List <string[]> keyColumns     = new List <string[]>();
            List <bool>     cascadeDeletes = new List <bool>();
            using (var kiter = persistentClass.KeyClosureIterator.GetEnumerator())
            {
                foreach (var tab in persistentClass.TableClosureIterator)
                {
                    kiter.MoveNext();
                    var key     = kiter.Current;
                    var tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                    tables.Add(tabname);

                    var keyCols         = new List <string>(idColumnSpan);
                    var enumerableKCols = new SafetyEnumerable <Column>(key.ColumnIterator);
                    foreach (var kcol in enumerableKCols)
                    {
                        keyCols.Add(kcol.GetQuotedName(factory.Dialect));
                    }

                    keyColumns.Add(keyCols.ToArray());
                    cascadeDeletes.Add(key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete);
                }
            }
            naturalOrderTableNames           = tables.ToArray();
            naturalOrderTableKeyColumns      = keyColumns.ToArray();
            naturalOrderCascadeDeleteEnabled = cascadeDeletes.ToArray();

            List <string> subtables   = new List <string>();
            List <bool>   isConcretes = new List <bool>();
            keyColumns = new List <string[]>();
            foreach (Table tab in persistentClass.SubclassTableClosureIterator)
            {
                isConcretes.Add(persistentClass.IsClassOrSuperclassTable(tab));
                string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                subtables.Add(tabname);
                List <string> key = new List <string>(idColumnSpan);
                foreach (Column column in tab.PrimaryKey.ColumnIterator)
                {
                    key.Add(column.GetQuotedName(factory.Dialect));
                }

                keyColumns.Add(key.ToArray());
            }
            subclassTableNameClosure      = subtables.ToArray();
            subclassTableKeyColumnClosure = keyColumns.ToArray();
            isClassOrSuperclassTable      = isConcretes.ToArray();

            constraintOrderedTableNames     = new string[subclassTableNameClosure.Length];
            constraintOrderedKeyColumnNames = new string[subclassTableNameClosure.Length][];
            int currentPosition = 0;
            for (int i = subclassTableNameClosure.Length - 1; i >= 0; i--, currentPosition++)
            {
                constraintOrderedTableNames[currentPosition]     = subclassTableNameClosure[i];
                constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i];
            }

            tableSpan       = naturalOrderTableNames.Length;
            tableNames      = Reverse(naturalOrderTableNames);
            tableKeyColumns = Reverse(naturalOrderTableKeyColumns);
            Reverse(subclassTableNameClosure, tableSpan);
            Reverse(subclassTableKeyColumnClosure, tableSpan);

            spaces = ArrayHelper.Join(tableNames, persistentClass.SynchronizedTables.ToArray());

            // Custom sql
            customSQLInsert         = new SqlString[tableSpan];
            customSQLUpdate         = new SqlString[tableSpan];
            customSQLDelete         = new SqlString[tableSpan];
            insertCallable          = new bool[tableSpan];
            updateCallable          = new bool[tableSpan];
            deleteCallable          = new bool[tableSpan];
            insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
            updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
            deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];

            PersistentClass pc = persistentClass;
            int             jk = tableSpan - 1;
            while (pc != null)
            {
                customSQLInsert[jk]         = pc.CustomSQLInsert;
                insertCallable[jk]          = customSQLInsert[jk] != null && pc.IsCustomInsertCallable;
                insertResultCheckStyles[jk] = pc.CustomSQLInsertCheckStyle
                                              ??
                                              ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[jk], insertCallable[jk]);
                customSQLUpdate[jk]         = pc.CustomSQLUpdate;
                updateCallable[jk]          = customSQLUpdate[jk] != null && pc.IsCustomUpdateCallable;
                updateResultCheckStyles[jk] = pc.CustomSQLUpdateCheckStyle
                                              ??
                                              ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[jk], updateCallable[jk]);
                customSQLDelete[jk]         = pc.CustomSQLDelete;
                deleteCallable[jk]          = customSQLDelete[jk] != null && pc.IsCustomDeleteCallable;
                deleteResultCheckStyles[jk] = pc.CustomSQLDeleteCheckStyle
                                              ??
                                              ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[jk], deleteCallable[jk]);
                jk--;
                pc = pc.Superclass;
            }
            if (jk != -1)
            {
                throw new AssertionFailure("Tablespan does not match height of joined-subclass hierarchy.");
            }

            #endregion

            #region PROPERTIES

            int hydrateSpan = PropertySpan;
            naturalOrderPropertyTableNumbers = new int[hydrateSpan];
            propertyTableNumbers             = new int[hydrateSpan];
            int i2 = 0;
            foreach (Property prop in persistentClass.PropertyClosureIterator)
            {
                string tabname = prop.Value.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                propertyTableNumbers[i2]             = GetTableId(tabname, tableNames);
                naturalOrderPropertyTableNumbers[i2] = GetTableId(tabname, naturalOrderTableNames);
                i2++;
            }

            // subclass closure properties
            List <int> columnTableNumbers  = new List <int>();
            List <int> formulaTableNumbers = new List <int>();
            List <int> propTableNumbers    = new List <int>();
            foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
            {
                Table  tab     = prop.Value.Table;
                string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                int    tabnum  = GetTableId(tabname, subclassTableNameClosure);
                propTableNumbers.Add(tabnum);

                foreach (ISelectable thing in prop.ColumnIterator)
                {
                    if (thing.IsFormula)
                    {
                        formulaTableNumbers.Add(tabnum);
                    }
                    else
                    {
                        columnTableNumbers.Add(tabnum);
                    }
                }
            }

            subclassColumnTableNumberClosure   = columnTableNumbers.ToArray();
            subclassPropertyTableNumberClosure = propTableNumbers.ToArray();
            subclassFormulaTableNumberClosure  = formulaTableNumbers.ToArray();
            #endregion

            #region SUBCLASSES

            int subclassSpan = persistentClass.SubclassSpan + 1;
            subclassClosure = new string[subclassSpan];
            subclassClosure[subclassSpan - 1] = EntityName;
            if (persistentClass.IsPolymorphic)
            {
                subclassesByDiscriminatorValue[discriminatorValue] = EntityName;
                discriminatorValues = new string[subclassSpan];
                discriminatorValues[subclassSpan - 1] = discriminatorSQLString;
                notNullColumnTableNumbers             = new int[subclassSpan];
                int id =
                    GetTableId(
                        persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
                                                               factory.Settings.DefaultSchemaName), subclassTableNameClosure);
                notNullColumnTableNumbers[subclassSpan - 1] = id;
                notNullColumnNames = new string[subclassSpan];
                notNullColumnNames[subclassSpan - 1] = subclassTableKeyColumnClosure[id][0];
                //( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
            }
            else
            {
                discriminatorValues       = null;
                notNullColumnTableNumbers = null;
                notNullColumnNames        = null;
            }

            int k2 = 0;
            foreach (Subclass sc in persistentClass.SubclassIterator)
            {
                subclassClosure[k2] = sc.EntityName;
                try
                {
                    if (persistentClass.IsPolymorphic)
                    {
                        // we now use subclass ids that are consistent across all
                        // persisters for a class hierarchy, so that the use of
                        // "foo.class = Bar" works in HQL
                        int subclassId = sc.SubclassId;                         //new Integer(k+1);
                        subclassesByDiscriminatorValue[subclassId] = sc.EntityName;
                        discriminatorValues[k2] = subclassId.ToString();
                        int id =
                            GetTableId(
                                sc.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
                                                          factory.Settings.DefaultSchemaName), subclassTableNameClosure);
                        notNullColumnTableNumbers[k2] = id;
                        notNullColumnNames[k2]        = subclassTableKeyColumnClosure[id][0];
                        //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
                    }
                }
                catch (Exception e)
                {
                    throw new MappingException("Error parsing discriminator value", e);
                }
                k2++;
            }

            #endregion

            InitLockers();

            InitSubclassPropertyAliasesMap(persistentClass);

            PostConstruct(mapping);
        }
		protected AbstractEntityPersister( PersistentClass model, ISessionFactoryImplementor factory )
		{
			dialect = factory.Dialect;
			//sqlExceptionConverter = factory.SQLExceptionConverter;

			// CLASS
			className = model.MappedClass.FullName;
			rootClassName = model.RootClazz.Name;
			mappedClass = model.MappedClass;

			mutable = model.IsMutable;
			selectBeforeUpdate = model.SelectBeforeUpdate;
			dynamicUpdate = model.DynamicUpdate;
			dynamicInsert = model.DynamicInsert;
			sqlWhereString = model.Where;
			sqlWhereStringTemplate = sqlWhereString == null ?
				null :
				Template.RenderWhereStringTemplate( sqlWhereString, Dialect );

			polymorphic = model.IsPolymorphic;
			explicitPolymorphism = model.IsExplicitPolymorphism;
			inherited = model.IsInherited;
			superclass = inherited ? model.Superclass.MappedClass : null;
			hasSubclasses = model.HasSubclasses;

			batchSize = model.BatchSize;

			constructor = ReflectHelper.GetDefaultConstructor( mappedClass );
			abstractClass = ReflectHelper.IsAbstractClass( mappedClass );

			entityType = NHibernateUtil.Entity( mappedClass );

			optimisticLockMode = model.OptimisticLockMode;
			if( optimisticLockMode > OptimisticLockMode.Version && !dynamicUpdate )
			{
				throw new MappingException( string.Format( "optimistic-lock setting requires dynamic-update=\'true\': {0}", className ) );
			}

			// verify that the class has a default constructor if it is not abstract - it is considered
			// a mapping exception if the default ctor is missing.
			if( abstractClass == false && constructor == null )
			{
				throw new MappingException( "The mapped class " + mappedClass.FullName + " must declare a default (no-arg) constructor." );
			}

			// IDENTIFIER
			hasEmbeddedIdentifier = model.HasEmbeddedIdentifier;
			IValue idValue = model.Identifier;
			identifierType = idValue.Type;

			if( model.HasIdentifierProperty )
			{
				Mapping.Property idProperty = model.IdentifierProperty;
				identifierPropertyName = idProperty.Name;
				identifierSetter = idProperty.GetSetter( mappedClass );
				identifierGetter = idProperty.GetGetter( mappedClass );
			}
			else
			{
				identifierPropertyName = null;
				identifierGetter = null;
				identifierSetter = null;
			}

			System.Type prox = model.ProxyInterface;
			MethodInfo proxySetIdentifierMethod = null;
			MethodInfo proxyGetIdentifierMethod = null;

			if( model.HasIdentifierProperty && prox != null )
			{
				Mapping.Property idProperty = model.IdentifierProperty;

				PropertyInfo getIdPropertyInfo = idProperty.GetGetter( prox ).Property;

				if( getIdPropertyInfo != null )
				{
					proxyGetIdentifierMethod = getIdPropertyInfo.GetGetMethod( true );
				}

				PropertyInfo setIdPropertyInfo = idProperty.GetSetter( prox ).Property;

				if( setIdPropertyInfo != null )
				{
					proxySetIdentifierMethod = setIdPropertyInfo.GetSetMethod( true );
				}
			}

			// HYDRATE SPAN
			hydrateSpan = model.PropertyClosureCollection.Count;

			// IDENTIFIER 
			int idColumnSpan = model.Identifier.ColumnSpan;
			identifierColumnNames = new string[idColumnSpan];
			identifierAliases = new string[idColumnSpan];

			int i = 0;
			foreach( Column col in idValue.ColumnCollection )
			{
				identifierColumnNames[ i ] = col.GetQuotedName( Dialect );
				identifierAliases[ i ] = col.Alias( Dialect );
				i++;
			}

			// GENERATOR
			identifierGenerator = model.Identifier.CreateIdentifierGenerator( Dialect );
			useIdentityColumn = identifierGenerator is IdentityGenerator;
			identitySelectString = useIdentityColumn ? dialect.IdentitySelectString : null;

			// UNSAVED-VALUE:
			unsavedIdentifierValue = UnsavedValueFactory.GetUnsavedIdentifierValue(
				model.Identifier.NullValue,
				identifierGetter,
				identifierType,
				constructor );

			// VERSION:

			if( model.IsVersioned )
			{
				foreach( Column col in model.Version.ColumnCollection )
				{
					versionColumnName = col.GetQuotedName( Dialect );
					break; //only happens once
				}
			}
			else
			{
				versionColumnName = null;
			}

			if( model.IsVersioned )
			{
				//versionPropertyName = model.Version.Name;
				versioned = true;
				versionGetter = model.Version.GetGetter( mappedClass );
				versionType = ( IVersionType ) model.Version.Type;
			}
			else
			{
				//versionPropertyName = null;
				versioned = false;
				versionGetter = null;
				versionType = null;
			}

			// VERSION UNSAVED-VALUE:
			unsavedVersionValue = model.IsVersioned ?
				UnsavedValueFactory.GetUnsavedVersionValue(
					model.Version.NullValue,
					versionGetter,
					versionType,
					constructor ) :
				Cascades.VersionValue.VersionUndefined;

			// PROPERTIES 

			propertyTypes = new IType[hydrateSpan];
			propertyNames = new string[hydrateSpan];
			propertyUpdateability = new bool[hydrateSpan];
			propertyInsertability = new bool[hydrateSpan];
			propertyNullability = new bool[hydrateSpan];
			getters = new IGetter[hydrateSpan];
			setters = new ISetter[hydrateSpan];
			cascadeStyles = new Cascades.CascadeStyle[hydrateSpan];
			string[ ] setterNames = new string[hydrateSpan];
			string[ ] getterNames = new string[hydrateSpan];
			System.Type[ ] types = new System.Type[hydrateSpan];

			i = 0;
			int tempVersionProperty = -66;
			bool foundCascade = false;
			
			bool foundCustomAccessor = false;

			foreach( Mapping.Property prop in model.PropertyClosureCollection )
			{
				if( prop == model.Version )
				{
					tempVersionProperty = i;
				}
				propertyNames[ i ] = prop.Name;
				if( !prop.IsBasicPropertyAccessor )
				{
					foundCustomAccessor = true;
				}

				getters[ i ] = prop.GetGetter( mappedClass );
				setters[ i ] = prop.GetSetter( mappedClass );
				getterNames[ i ] = getters[ i ].PropertyName;
				setterNames[ i ] = setters[ i ].PropertyName;
				types[ i ] = getters[ i ].ReturnType;
				propertyTypes[ i ] = prop.Type;
				propertyUpdateability[ i ] = prop.IsUpdateable;
				propertyInsertability[ i ] = prop.IsInsertable;
				propertyNullability[ i ] = prop.IsNullable;

				gettersByPropertyName[ propertyNames[ i ] ] = getters[ i ];
				settersByPropertyName[ propertyNames[ i ] ] = setters[ i ];
				typesByPropertyName[ propertyNames[ i ] ] = propertyTypes[ i ];

				cascadeStyles[ i ] = prop.CascadeStyle;
				if( cascadeStyles[ i ] != Cascades.CascadeStyle.StyleNone )
				{
					foundCascade = true;
				}

				i++;
			}

			// NH: reflection optimizer works with custom accessors
			if( /*!foundCustomAccessor &&*/ Cfg.Environment.UseReflectionOptimizer )
			{
				getset = GetSetHelperFactory.Create( MappedClass, Setters, Getters );
			}

			hasCascades = foundCascade;
			versionProperty = tempVersionProperty;

			// CALLBACK INTERFACES
			implementsLifecycle = typeof( ILifecycle ).IsAssignableFrom( mappedClass );
			implementsValidatable = typeof( IValidatable ).IsAssignableFrom( mappedClass );

			cache = model.Cache;

			hasCollections = InitHasCollections();

			// PROXIES
			concreteProxyClass = model.ProxyInterface;
			hasProxy = concreteProxyClass != null;

			if( hasProxy )
			{
				HashedSet proxyInterfaces = new HashedSet();
				proxyInterfaces.Add( typeof( INHibernateProxy ) );

				if( !mappedClass.Equals( concreteProxyClass ) )
				{
					if( !concreteProxyClass.IsInterface )
					{
						throw new MappingException(
							"proxy must be either an interface, or the class itself: " +
								mappedClass.FullName );
					}

					proxyInterfaces.Add( concreteProxyClass );
				}

				if( mappedClass.IsInterface )
				{
					proxyInterfaces.Add( mappedClass );
				}

				if( hasProxy )
				{
					foreach( Subclass subclass in model.SubclassCollection )
					{
						System.Type subclassProxy = subclass.ProxyInterface;
						if( subclassProxy == null )
						{
							throw new MappingException( "All subclasses must also have proxies: "
								+ mappedClass.Name );
						}

						if( !subclass.MappedClass.Equals( subclassProxy ) )
						{
							proxyInterfaces.Add( subclassProxy );
						}
					}
				}

				if( hasProxy )
				{
					proxyFactory = CreateProxyFactory();
					proxyFactory.PostInstantiate( mappedClass, proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod );
				}
				else
				{
					proxyFactory = null;
				}
			}
			else
			{
				proxyFactory = null;
			}
		}
		/// <summary>
		/// Set up a cache for a collection role
		/// </summary>
		public Configuration SetCacheConcurrencyStrategy( string collectionRole, ICacheConcurrencyStrategy concurrencyStrategy )
		{
			SetCacheConcurrencyStrategy( collectionRole, concurrencyStrategy, collectionRole );
			return this;
		}
		/// <summary>
		/// Set up a cache for an entity class
		/// </summary>
		public Configuration SetCacheConcurrencyStrategy( System.Type clazz, ICacheConcurrencyStrategy concurrencyStrategy )
		{
			SetCacheConcurrencyStrategy( clazz, concurrencyStrategy, clazz.FullName );
			return this;
		}
		//INITIALIZATION:

		public SingleTableEntityPersister(PersistentClass model, ICacheConcurrencyStrategy cache,
		                                  ISessionFactoryImplementor factory, IMapping mapping)
			: base(model, cache, factory)
		{
			// CLASS + TABLE

			System.Type mappedClass = model.MappedClass;
			Table table = model.RootTable;
			qualifiedTableName = table.GetQualifiedName(Dialect, factory.DefaultSchema);
			tableNames = new string[] {qualifiedTableName};

			// Custom sql
			customSQLInsert = new SqlString[1];
			customSQLUpdate = new SqlString[1];
			customSQLDelete = new SqlString[1];
			insertCallable = new bool[1];
			updateCallable = new bool[1];
			deleteCallable = new bool[1];
			insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
			updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
			deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];

			customSQLInsert[0] = model.CustomSQLInsert;
			insertCallable[0] = customSQLInsert[0] != null && model.IsCustomInsertCallable;
			insertResultCheckStyles[0] = model.CustomSQLInsertCheckStyle == null
			                             	?
			                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0])
			                             	: model.CustomSQLInsertCheckStyle;
			customSQLUpdate[0] = model.CustomSQLUpdate;
			updateCallable[0] = customSQLUpdate[0] != null && model.IsCustomUpdateCallable;
			updateResultCheckStyles[0] = model.CustomSQLUpdateCheckStyle == null
			                             	?
			                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0])
			                             	: model.CustomSQLUpdateCheckStyle;
			customSQLDelete[0] = model.CustomSQLDelete;
			deleteCallable[0] = customSQLDelete[0] != null && model.IsCustomDeleteCallable;
			deleteResultCheckStyles[0] = model.CustomSQLDeleteCheckStyle == null
			                             	?
			                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0])
			                             	: model.CustomSQLDeleteCheckStyle;

			// detect mapping errors
			HashedSet distinctColumns = new HashedSet();

			// DISCRIMINATOR
			if (model.IsPolymorphic)
			{
				IValue d = model.Discriminator;
				if (d == null)
				{
					throw new MappingException("A discriminator mapping required for polymorphic persistence of " + model.Name);
				}
				forceDiscriminator = model.IsForceDiscriminator;

				// the discriminator will have only one column 
				foreach (ISelectable selectable in d.ColumnCollection)
				{
					if (d.HasFormula)
					{
						Formula formula = (Formula) selectable;
						discriminatorFormula = formula.FormulaString;
						discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
						discriminatorColumnName = null;
						discriminatorAlias = "clazz_";
					}
					else
					{
						Column column = (Column) selectable;
						discriminatorColumnName = column.GetQuotedName(Dialect);
						discriminatorAlias = column.GetAlias(Dialect);
						discriminatorFormula = null;
						discriminatorFormulaTemplate = null;
					}
				}
				discriminatorType = model.Discriminator.Type;

				if (model.IsDiscriminatorValueNull)
				{
					discriminatorValue = NullDiscriminator;
					discriminatorSQLValue = InFragment.Null;
					discriminatorInsertable = false;
				}
				else if (model.IsDiscriminatorValueNotNull)
				{
					discriminatorValue = NotNullDiscriminator;
					discriminatorSQLValue = InFragment.NotNull;
					discriminatorInsertable = false;
				}
				else
				{
					discriminatorInsertable = model.IsDiscriminatorInsertable && !d.HasFormula;
					try
					{
						IDiscriminatorType dtype = (IDiscriminatorType) discriminatorType;
						discriminatorValue = dtype.StringToObject(model.DiscriminatorValue);
						discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue);
					}
					catch (InvalidCastException)
					{
						throw new MappingException(string.Format("Illegal discriminator type: {0}", discriminatorType.Name));
					}
					catch (Exception e)
					{
						string msg = String.Format("Could not format discriminator value '{0}' to sql string using the IType {1}",
						                           model.DiscriminatorValue,
						                           model.Discriminator.Type.ToString());

						throw new MappingException(msg, e);
					}

					if (discriminatorInsertable)
					{
						distinctColumns.Add(discriminatorColumnName);
					}
				}
			}
			else
			{
				forceDiscriminator = false;
				discriminatorInsertable = false;
				discriminatorColumnName = null;
				discriminatorAlias = null;
				discriminatorType = null;
				discriminatorValue = null;
				discriminatorSQLValue = null;
			}

			// PROPERTIES
			HashedSet thisClassProperties = new HashedSet();

			foreach (Mapping.Property prop in model.PropertyClosureCollection)
			{
				thisClassProperties.Add(prop);
			}

			// SQL string generation moved to PostInstantiate

			int subclassSpan = model.SubclassSpan + 1;
			subclassClosure = new System.Type[subclassSpan];
			subclassClosure[0] = mappedClass;
			if (model.IsPolymorphic)
			{
				subclassesByDiscriminatorValue.Add(discriminatorValue, mappedClass);
			}

			// SUBCLASSES
			if (model.IsPolymorphic)
			{
				int k = 1;
				foreach (Subclass sc in model.SubclassCollection)
				{
					subclassClosure[k++] = sc.MappedClass;
					if (sc.IsDiscriminatorValueNull)
					{
						subclassesByDiscriminatorValue.Add(NullDiscriminator, sc.MappedClass);
					}
					else if (sc.IsDiscriminatorValueNotNull)
					{
						subclassesByDiscriminatorValue.Add(NotNullDiscriminator, sc.MappedClass);
					}
					else
					{
						try
						{
							IDiscriminatorType dtype = discriminatorType as IDiscriminatorType;
							subclassesByDiscriminatorValue.Add(
								dtype.StringToObject(sc.DiscriminatorValue),
								sc.MappedClass);
						}
						catch (InvalidCastException)
						{
							throw new MappingException(string.Format("Illegal discriminator type: {0}", discriminatorType.Name));
						}
						catch (Exception e)
						{
							throw new MappingException(string.Format("Error parsing discriminator value: '{0}'", sc.DiscriminatorValue), e);
						}
					}
				}
			}

			// This is in PostInstatiate as it needs identifier info
			//InitLockers();

			propertyTableNumbers = new int[EntityMetamodel.PropertySpan];
			for (int i = 0; i < propertyTableNumbers.Length; i++)
			{
				propertyTableNumbers[i] = 0;
			}

			InitSubclassPropertyAliasesMap(model);
			PostConstruct(mapping);
		}
Пример #42
0
		public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model,
												  ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, Configuration cfg)
		{
			ConstructorInfo pc;
			var use4Parameters = false;
			try
			{
				pc = persisterClass.GetConstructor(CollectionPersisterConstructorArgs);
				if (pc == null)
				{
					use4Parameters = true;
					pc = persisterClass.GetConstructor(CollectionPersisterConstructor2Args);
				}
			}
			catch (Exception e)
			{
				throw new MappingException("Could not get constructor for " + persisterClass.Name, e);
			}
			if(pc == null)
			{
				var messageBuilder = new StringBuilder();
				messageBuilder.AppendLine("Could not find a public constructor for " + persisterClass.Name +";");
				messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructorArgs.Length + " parameters of types (in order):");
				System.Array.ForEach(CollectionPersisterConstructorArgs, t=> messageBuilder.AppendLine(t.FullName));
				messageBuilder.AppendLine();
				messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructor2Args.Length + " parameters of types (in order):");
				System.Array.ForEach(CollectionPersisterConstructor2Args, t => messageBuilder.AppendLine(t.FullName));
				throw new MappingException(messageBuilder.ToString());
			}
			try
			{
				if (!use4Parameters)
				{
					return (ICollectionPersister) pc.Invoke(new object[] {model, cache, factory});
				}
				return (ICollectionPersister)pc.Invoke(new object[] { model, cache, cfg, factory });
			}
			catch (TargetInvocationException tie)
			{
				Exception e = tie.InnerException;
				if (e is HibernateException)
				{
					throw e;
				}
				else
				{
					throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e);
				}
			}
			catch (Exception e)
			{
				throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e);
			}
		}
		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.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);

			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);
				// NH see : identityDelegate declaration
				IPostInsertIdentifierGenerator pig = (identifierGenerator as IPostInsertIdentifierGenerator);
				if (pig != null)
				{
					identityDelegate = pig.GetInsertGeneratedIdentifierDelegate(this, Factory, UseGetGeneratedKeys());
				}
				else
				{
					identityDelegate = null;
				}

				CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnIterator);
			}
			else
			{
				identifierType = null;
				identifierColumnName = null;
				identifierColumnAlias = null;
				identifierGenerator = null;
				identityDelegate = null;
			}

			#endregion

			#region GENERATE THE SQL

			// NH Different behavior : for the Insert SQL we are managing isPostInsertIdentifier (not supported in H3.2.5) 
			if (collection.CustomSQLInsert == null)
			{
				if (!IsIdentifierAssignedByInsert)
				{
					sqlInsertRowString = GenerateInsertRowString();
				}
				else
				{
					sqlInsertRowString = GenerateIdentityInsertRowString();
				}
				insertCallable = false;
				insertCheckStyle = ExecuteUpdateResultCheckStyle.Count;
			}
			else
			{
				SqlType[] parmsTypes = GenerateInsertRowString().ParameterTypes;
				sqlInsertRowString = new SqlCommandInfo(collection.CustomSQLInsert, parmsTypes);
				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;
			}

		    isCollectionIntegerIndex = 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
			{
				// for non-arrays, we don't need to know the element class
				elementClass = null;
			}

			if (elementType.IsComponentType)
			{
				elementPropertyMapping =
					new CompositeElementPropertyMapping(elementColumnNames, elementFormulaTemplates,
					                                    (IAbstractComponentType) elementType, factory);
			}
			else if (!elementType.IsEntityType)
			{
				elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType);
			}
			else
			{
				elementPropertyMapping = elementPersister as IPropertyMapping;
				if (elementPropertyMapping == null)
				{
					elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType);
				}
			}

			// Handle any filters applied to this collection
			filterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry);

			// Handle any filters applied to this collection for many-to-many
			manyToManyFilterHelper = new FilterHelper(collection.ManyToManyFilterMap, dialect, factory.SQLFunctionRegistry);
			manyToManyWhereString = !string.IsNullOrEmpty(collection.ManyToManyWhere)
			                        	? "( " + collection.ManyToManyWhere + " )"
			                        	: null;
			manyToManyWhereTemplate = manyToManyWhereString == null
			                          	? null
			                          	: Template.RenderWhereStringTemplate(manyToManyWhereString, factory.Dialect,
			                          	                                     factory.SQLFunctionRegistry);
			manyToManyOrderByString = collection.ManyToManyOrdering;
			manyToManyOrderByTemplate = manyToManyOrderByString == null
			                            	? null
			                            	: Template.RenderOrderByStringTemplate(manyToManyOrderByString, factory.Dialect,
			                            	                                       factory.SQLFunctionRegistry);
			InitCollectionPropertyMap();
		}
		protected AbstractEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
		                                  ISessionFactoryImplementor factory)
		{
			this.factory = factory;
			dialect = factory.Dialect;
			this.cache = cache;
			//sqlExceptionConverter = factory.SQLExceptionConverter;

			entityMetamodel = new EntityMetamodel(persistentClass, factory);

			// CLASS
			mappedClass = persistentClass.MappedClass;

			sqlWhereString = persistentClass.Where;
			sqlWhereStringTemplate = sqlWhereString == null
			                         	?
			                         null
			                         	:
			                         Template.RenderWhereStringTemplate(sqlWhereString, Dialect, factory.SQLFunctionRegistry);

			batchSize = persistentClass.BatchSize;
			hasSubselectLoadableCollections = persistentClass.HasSubselectLoadableCollections;
			constructor = ReflectHelper.GetDefaultConstructor(mappedClass);

			// verify that the class has a default constructor if it is not abstract - it is considered
			// a mapping exception if the default ctor is missing.
			if (!entityMetamodel.IsAbstract && constructor == null)
			{
				throw new MappingException("The mapped class " + mappedClass.FullName +
				                           " must declare a default (no-arg) constructor.");
			}

			// IDENTIFIER
			hasEmbeddedIdentifier = persistentClass.HasEmbeddedIdentifier;
			IValue idValue = persistentClass.Identifier;

			if (persistentClass.HasIdentifierProperty)
			{
				Mapping.Property idProperty = persistentClass.IdentifierProperty;
				identifierSetter = idProperty.GetSetter(mappedClass);
				identifierGetter = idProperty.GetGetter(mappedClass);
			}
			else
			{
				identifierGetter = null;
				identifierSetter = null;
			}

			System.Type prox = persistentClass.ProxyInterface;
			MethodInfo proxySetIdentifierMethod = null;
			MethodInfo proxyGetIdentifierMethod = null;

			if (persistentClass.HasIdentifierProperty && prox != null)
			{
				Mapping.Property idProperty = persistentClass.IdentifierProperty;
				proxyGetIdentifierMethod = idProperty.GetGetter(prox).Method;
				proxySetIdentifierMethod = idProperty.GetSetter(prox).Method;
			}

			// HYDRATE SPAN
			hydrateSpan = persistentClass.PropertyClosureCollection.Count;

			// IDENTIFIER 

			identifierColumnSpan = persistentClass.Identifier.ColumnSpan;
			rootTableKeyColumnNames = new string[identifierColumnSpan];
			identifierAliases = new string[identifierColumnSpan];

			loaderName = persistentClass.LoaderName;

			int i = 0;
			foreach (Column col in idValue.ColumnCollection)
			{
				rootTableKeyColumnNames[i] = col.GetQuotedName(factory.Dialect);
				identifierAliases[i] = col.GetAlias(Dialect, persistentClass.RootTable);
				i++;
			}

			// VERSION:

			if (persistentClass.IsVersioned)
			{
				foreach (Column col in persistentClass.Version.ColumnCollection)
				{
					versionColumnName = col.GetQuotedName(Dialect);
					break; //only happens once
				}
			}
			else
			{
				versionColumnName = null;
			}

			if (persistentClass.IsVersioned)
			{
				versionGetter = persistentClass.Version.GetGetter(mappedClass);
				versionType = (IVersionType) persistentClass.Version.Type;
			}
			else
			{
				versionGetter = null;
				versionType = null;
			}

			// PROPERTIES 

			getters = new IGetter[hydrateSpan];
			setters = new ISetter[hydrateSpan];
			string[] setterNames = new string[hydrateSpan];
			string[] getterNames = new string[hydrateSpan];
			System.Type[] classes = new System.Type[hydrateSpan];

			i = 0;

			// NH: reflection optimizer works with custom accessors
			//bool foundCustomAccessor = false;

			foreach (Mapping.Property prop in persistentClass.PropertyClosureCollection)
			{
				//if( !prop.IsBasicPropertyAccessor )
				//{
				//	foundCustomAccessor = true;
				//}

				getters[i] = prop.GetGetter(mappedClass);
				setters[i] = prop.GetSetter(mappedClass);
				getterNames[i] = getters[i].PropertyName;
				setterNames[i] = setters[i].PropertyName;
				classes[i] = getters[i].ReturnType;

				string propertyName = prop.Name;
				gettersByPropertyName[propertyName] = getters[i];
				settersByPropertyName[propertyName] = setters[i];

				i++;
			}

			// PROPERTIES (FROM ABSTRACTENTITYPERSISTER SUBCLASSES)
			propertyColumnNames = new string[HydrateSpan][];
			propertyColumnAliases = new string[HydrateSpan][];
			propertyColumnSpans = new int[HydrateSpan];
			propertyColumnFormulaTemplates = new string[HydrateSpan][];
			propertyColumnUpdateable = new bool[HydrateSpan][];
			propertyColumnInsertable = new bool[HydrateSpan][];
			propertyUniqueness = new bool[HydrateSpan];

			HashedSet thisClassProperties = new HashedSet();
			i = 0;
			bool foundFormula = false;

			foreach (Mapping.Property prop in persistentClass.PropertyClosureCollection)
			{
				thisClassProperties.Add(prop);

				int span = prop.ColumnSpan;
				propertyColumnSpans[i] = span;
				string[] colNames = new string[span];
				string[] colAliases = new string[span];
				string[] templates = new string[span];

				int k = 0;
				foreach (ISelectable thing in prop.ColumnCollection)
				{
					colAliases[k] = thing.GetAlias(factory.Dialect, prop.Value.Table);
					if (thing.IsFormula)
					{
						foundFormula = true;
						templates[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
					}
					else
					{
						colNames[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
					}
					k++;
				}
				propertyColumnNames[i] = colNames;
				propertyColumnFormulaTemplates[i] = templates;
				propertyColumnAliases[i] = colAliases;
				propertyColumnInsertable[i] = prop.Value.ColumnInsertability;
				propertyColumnUpdateable[i] = prop.Value.ColumnUpdateability;
				propertyUniqueness[i] = prop.Value.IsUnique;

				i++;
			}

			hasFormulaProperties = foundFormula;

			// NH: reflection optimizer works with custom accessors
			if (Environment.UseReflectionOptimizer)
			{
				optimizer = Environment.BytecodeProvider.GetReflectionOptimizer(MappedClass, Getters, Setters);
			}

			// SUBCLASS PROPERTY CLOSURE

			ArrayList columns = new ArrayList(); //this.subclassColumnClosure
			ArrayList aliases = new ArrayList();
			ArrayList formulaAliases = new ArrayList();
			ArrayList formulaTemplates = new ArrayList();
			ArrayList types = new ArrayList(); //this.subclassPropertyTypeClosure
			ArrayList names = new ArrayList(); //this.subclassPropertyNameClosure
			ArrayList subclassTemplates = new ArrayList();
			ArrayList propColumns = new ArrayList(); //this.subclassPropertyColumnNameClosure
			ArrayList joinedFetchesList = new ArrayList(); //this.subclassPropertyEnableJoinedFetch
			ArrayList cascades = new ArrayList();
			ArrayList definedBySubclass = new ArrayList(); // this.propertyDefinedOnSubclass
			ArrayList formulas = new ArrayList();
			ArrayList propNullables = new ArrayList();

			foreach (Mapping.Property prop in persistentClass.SubclassPropertyClosureCollection)
			{
				names.Add(prop.Name);
				bool isDefinedBySubclass = !thisClassProperties.Contains(prop);
				definedBySubclass.Add(isDefinedBySubclass);
				propNullables.Add(prop.IsOptional || isDefinedBySubclass); //TODO: is this completely correct?
				types.Add(prop.Type);

				string[] cols = new string[prop.ColumnSpan];
				string[] forms = new string[prop.ColumnSpan];
				int[] colnos = new int[prop.ColumnSpan];
				int[] formnos = new int[prop.ColumnSpan];
				int l = 0;

				foreach (ISelectable thing in prop.ColumnCollection)
				{
					if (thing.IsFormula)
					{
						string template = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
						formnos[l] = formulaTemplates.Count;
						colnos[l] = -1;
						formulaTemplates.Add(template);
						forms[l] = template;
						formulas.Add(thing.GetText(factory.Dialect));
						formulaAliases.Add(thing.GetAlias(factory.Dialect));
						// TODO H3: formulasLazy.add( lazy );
					}
					else
					{
						String colName = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
						colnos[l] = columns.Count; //before add :-)
						formnos[l] = -1;
						columns.Add(colName);
						cols[l] = colName;
						aliases.Add(thing.GetAlias(factory.Dialect, prop.Value.Table));
						// TODO H3: columnsLazy.add( lazy );
						// TODO H3: columnSelectables.add( new Boolean( prop.isSelectable() ) );
					}
					l++;
				}

				propColumns.Add(cols);
				subclassTemplates.Add(forms);
				//propColumnNumbers.Add( colnos );
				//propFormulaNumbers.Add( formnos );

				joinedFetchesList.Add(prop.Value.FetchMode);
				cascades.Add(prop.CascadeStyle);
			}

			subclassColumnClosure = (string[]) columns.ToArray(typeof(string));
			subclassFormulaClosure = (string[]) formulas.ToArray(typeof(string));
			subclassFormulaTemplateClosure = (string[]) formulaTemplates.ToArray(typeof(string));
			subclassPropertyTypeClosure = (IType[]) types.ToArray(typeof(IType));
			subclassColumnAliasClosure = (string[]) aliases.ToArray(typeof(string));
			subclassFormulaAliasClosure = (string[]) formulaAliases.ToArray(typeof(string));
			subclassPropertyNameClosure = (string[]) names.ToArray(typeof(string));
			subclassPropertyNullabilityClosure = (bool[]) propNullables.ToArray(typeof(bool));
			subclassPropertyFormulaTemplateClosure = ArrayHelper.To2DStringArray(subclassTemplates);
			subclassPropertyColumnNameClosure = (string[][]) propColumns.ToArray(typeof(string[]));

			subclassPropertyCascadeStyleClosure = new Cascades.CascadeStyle[cascades.Count];
			int m = 0;
			foreach (Cascades.CascadeStyle cs in cascades)
			{
				subclassPropertyCascadeStyleClosure[m++] = cs;
			}

			subclassPropertyFetchModeClosure = new FetchMode[joinedFetchesList.Count];
			m = 0;
			foreach (FetchMode qq in joinedFetchesList)
			{
				subclassPropertyFetchModeClosure[m++] = qq;
			}

			propertyDefinedOnSubclass = new bool[definedBySubclass.Count];
			m = 0;
			foreach (bool val in definedBySubclass)
			{
				propertyDefinedOnSubclass[m++] = val;
			}

			// CALLBACK INTERFACES
			implementsLifecycle = typeof(ILifecycle).IsAssignableFrom(mappedClass);
			implementsValidatable = typeof(IValidatable).IsAssignableFrom(mappedClass);

			// PROXIES
			concreteProxyClass = persistentClass.ProxyInterface;
			bool hasProxy = concreteProxyClass != null;

			if (hasProxy)
			{
				HashedSet proxyInterfaces = new HashedSet();
				proxyInterfaces.Add(typeof(INHibernateProxy));

				if (!mappedClass.Equals(concreteProxyClass))
				{
					if (!concreteProxyClass.IsInterface)
					{
						throw new MappingException(
							"proxy must be either an interface, or the class itself: " +
							mappedClass.FullName);
					}

					proxyInterfaces.Add(concreteProxyClass);
				}

				if (mappedClass.IsInterface)
				{
					proxyInterfaces.Add(mappedClass);
				}

				if (HasProxy)
				{
					foreach (Subclass subclass in persistentClass.SubclassCollection)
					{
						System.Type subclassProxy = subclass.ProxyInterface;
						if (subclassProxy == null)
						{
							throw new MappingException("All subclasses must also have proxies: "
							                           + mappedClass.Name);
						}

						if (!subclass.MappedClass.Equals(subclassProxy))
						{
							proxyInterfaces.Add(subclassProxy);
						}
					}
				}

				if (HasProxy)
				{
					proxyFactory = CreateProxyFactory();
					proxyFactory.PostInstantiate(mappedClass, proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod);
				}
				else
				{
					proxyFactory = null;
				}
			}
			else
			{
				proxyFactory = null;
			}

			// Handle any filters applied to the class level
			filterHelper = new FilterHelper(persistentClass.FilterMap, factory.Dialect, factory.SQLFunctionRegistry);
		}
		public SingleTableEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
																			ISessionFactoryImplementor factory, IMapping mapping)
			: base(persistentClass, cache, factory)
		{
			#region CLASS + TABLE

			joinSpan = persistentClass.JoinClosureSpan + 1;
			qualifiedTableNames = new string[joinSpan];
			isInverseTable = new bool[joinSpan];
			isNullableTable = new bool[joinSpan];
			keyColumnNames = new string[joinSpan][];
			Table table = persistentClass.RootTable;
			qualifiedTableNames[0] =
				table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
			isInverseTable[0] = false;
			isNullableTable[0] = false;
			keyColumnNames[0] = IdentifierColumnNames;
			cascadeDeleteEnabled = new bool[joinSpan];

			// Custom sql
			customSQLInsert = new SqlString[joinSpan];
			customSQLUpdate = new SqlString[joinSpan];
			customSQLDelete = new SqlString[joinSpan];
			insertCallable = new bool[joinSpan];
			updateCallable = new bool[joinSpan];
			deleteCallable = new bool[joinSpan];
			insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
			updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
			deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];

			customSQLInsert[0] = persistentClass.CustomSQLInsert;
			insertCallable[0] = customSQLInsert[0] != null && persistentClass.IsCustomInsertCallable;
			insertResultCheckStyles[0] = persistentClass.CustomSQLInsertCheckStyle
																	 ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0]);
			customSQLUpdate[0] = persistentClass.CustomSQLUpdate;
			updateCallable[0] = customSQLUpdate[0] != null && persistentClass.IsCustomUpdateCallable;
			updateResultCheckStyles[0] = persistentClass.CustomSQLUpdateCheckStyle
																	 ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0]);
			customSQLDelete[0] = persistentClass.CustomSQLDelete;
			deleteCallable[0] = customSQLDelete[0] != null && persistentClass.IsCustomDeleteCallable;
			deleteResultCheckStyles[0] = persistentClass.CustomSQLDeleteCheckStyle
																	 ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0]);

			#endregion

			#region JOINS
			int j = 1;
			foreach (Join join in persistentClass.JoinClosureIterator)
			{
				qualifiedTableNames[j] = join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				isInverseTable[j] = join.IsInverse;
				isNullableTable[j] = join.IsOptional;
				cascadeDeleteEnabled[j] = join.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete;

				customSQLInsert[j] = join.CustomSQLInsert;
				insertCallable[j] = customSQLInsert[j] != null && join.IsCustomInsertCallable;
				insertResultCheckStyles[j] = join.CustomSQLInsertCheckStyle
																		 ??
																		 ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[j], insertCallable[j]);
				customSQLUpdate[j] = join.CustomSQLUpdate;
				updateCallable[j] = customSQLUpdate[j] != null && join.IsCustomUpdateCallable;
				updateResultCheckStyles[j] = join.CustomSQLUpdateCheckStyle
																		 ??
																		 ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[j], updateCallable[j]);
				customSQLDelete[j] = join.CustomSQLDelete;
				deleteCallable[j] = customSQLDelete[j] != null && join.IsCustomDeleteCallable;
				deleteResultCheckStyles[j] = join.CustomSQLDeleteCheckStyle
																		 ??
																		 ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[j], deleteCallable[j]);

				IEnumerable<Column> enumerableKeyCol = new SafetyEnumerable<Column>(join.Key.ColumnIterator);
				List<string> kcName = new List<string>(join.Key.ColumnSpan);
				foreach (Column col in enumerableKeyCol)
					kcName.Add(col.GetQuotedName(factory.Dialect));

				keyColumnNames[j] = kcName.ToArray();

				j++;
			}

			constraintOrderedTableNames = new string[qualifiedTableNames.Length];
			constraintOrderedKeyColumnNames = new string[qualifiedTableNames.Length][];
			for (int i = qualifiedTableNames.Length - 1, position = 0; i >= 0; i--, position++)
			{
				constraintOrderedTableNames[position] = qualifiedTableNames[i];
				constraintOrderedKeyColumnNames[position] = keyColumnNames[i];
			}

			spaces = ArrayHelper.Join(qualifiedTableNames, ArrayHelper.ToStringArray(persistentClass.SynchronizedTables));

			bool lazyAvailable = IsInstrumented(EntityMode.Poco);

			bool hasDeferred = false;
			List<string> subclassTables = new List<string>();
			List<string[]> joinKeyColumns = new List<string[]>();
			List<bool> isConcretes = new List<bool>();
			List<bool> isDeferreds = new List<bool>();
			List<bool> isInverses = new List<bool>();
			List<bool> isNullables = new List<bool>();
			List<bool> isLazies = new List<bool>();
			subclassTables.Add(qualifiedTableNames[0]);
			joinKeyColumns.Add(IdentifierColumnNames);
			isConcretes.Add(true);
			isDeferreds.Add(false);
			isInverses.Add(false);
			isNullables.Add(false);
			isLazies.Add(false);
			foreach (Join join in persistentClass.SubclassJoinClosureIterator)
			{
				isConcretes.Add(persistentClass.IsClassOrSuperclassJoin(join));
				isDeferreds.Add(join.IsSequentialSelect);
				isInverses.Add(join.IsInverse);
				isNullables.Add(join.IsOptional);
				isLazies.Add(lazyAvailable && join.IsLazy);
				if (join.IsSequentialSelect && !persistentClass.IsClassOrSuperclassJoin(join))
					hasDeferred = true;
				subclassTables.Add(join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName));
				IEnumerable<Column> enumerableKeyCol = new SafetyEnumerable<Column>(join.Key.ColumnIterator);
				List<string> keyCols = new List<string>(join.Key.ColumnSpan);
				foreach (Column col in enumerableKeyCol)
					keyCols.Add(col.GetQuotedName(factory.Dialect));

				joinKeyColumns.Add(keyCols.ToArray());
			}

			subclassTableSequentialSelect = isDeferreds.ToArray();
			subclassTableNameClosure = subclassTables.ToArray();
			subclassTableIsLazyClosure = isLazies.ToArray();
			subclassTableKeyColumnClosure = joinKeyColumns.ToArray();
			isClassOrSuperclassTable = isConcretes.ToArray();
			isInverseSubclassTable = isInverses.ToArray();
			isNullableSubclassTable = isNullables.ToArray();
			hasSequentialSelects = hasDeferred;

			#endregion

			#region DISCRIMINATOR

			if (persistentClass.IsPolymorphic)
			{
				IValue discrimValue = persistentClass.Discriminator;
				if (discrimValue == null)
					throw new MappingException("Discriminator mapping required for single table polymorphic persistence");

				forceDiscriminator = persistentClass.IsForceDiscriminator;
				IEnumerator<ISelectable> iSel = discrimValue.ColumnIterator.GetEnumerator();
				iSel.MoveNext();
				ISelectable selectable = iSel.Current;
				if (discrimValue.HasFormula)
				{
					Formula formula = (Formula)selectable;
					discriminatorFormula = formula.FormulaString;
					discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
					discriminatorColumnName = null;
					discriminatorAlias = Discriminator_Alias;
				}
				else
				{
					Column column = (Column)selectable;
					discriminatorColumnName = column.GetQuotedName(factory.Dialect);
					discriminatorAlias = column.GetAlias(factory.Dialect, persistentClass.RootTable);
					discriminatorFormula = null;
					discriminatorFormulaTemplate = null;
				}
				discriminatorType = persistentClass.Discriminator.Type;
				if (persistentClass.IsDiscriminatorValueNull)
				{
					discriminatorValue = NullDiscriminator;
					discriminatorSQLValue = InFragment.Null;
					discriminatorInsertable = false;
				}
				else if (persistentClass.IsDiscriminatorValueNotNull)
				{
					discriminatorValue = NotNullDiscriminator;
					discriminatorSQLValue = InFragment.NotNull;
					discriminatorInsertable = false;
				}
				else
				{
					discriminatorInsertable = persistentClass.IsDiscriminatorInsertable && !discrimValue.HasFormula;
					try
					{
						IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
						discriminatorValue = dtype.StringToObject(persistentClass.DiscriminatorValue);
						discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue, factory.Dialect);
					}
					catch (InvalidCastException cce)
					{
						throw new MappingException(
							string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
					}
					catch (Exception e)
					{
						throw new MappingException("Could not format discriminator value to SQL string of entity " + persistentClass.EntityName, e);
					}
				}
			}
			else
			{
				forceDiscriminator = false;
				discriminatorInsertable = false;
				discriminatorColumnName = null;
				discriminatorAlias = null;
				discriminatorType = null;
				discriminatorValue = null;
				discriminatorSQLValue = null;
				discriminatorFormula = null;
				discriminatorFormulaTemplate = null;
			}

			#endregion

			#region PROPERTIES

			propertyTableNumbers = new int[PropertySpan];
			int i2 = 0;
			foreach (Property prop in persistentClass.PropertyClosureIterator)
			{
				propertyTableNumbers[i2++] = persistentClass.GetJoinNumber(prop);
			}

			List<int> columnJoinNumbers = new List<int>();
			List<int> formulaJoinedNumbers = new List<int>();
			List<int> propertyJoinNumbers = new List<int>();
			foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
			{
				int join = persistentClass.GetJoinNumber(prop);
				propertyJoinNumbers.Add(join);

				//propertyTableNumbersByName.put( prop.getName(), join );
				propertyTableNumbersByNameAndSubclass[prop.PersistentClass.EntityName + '.' + prop.Name] = join;
				foreach (ISelectable thing in prop.ColumnIterator)
				{
					if (thing.IsFormula)
						formulaJoinedNumbers.Add(join);
					else
						columnJoinNumbers.Add(join);
				}
			}

			subclassColumnTableNumberClosure = columnJoinNumbers.ToArray();
			subclassFormulaTableNumberClosure = formulaJoinedNumbers.ToArray();
			subclassPropertyTableNumberClosure = propertyJoinNumbers.ToArray();

			int subclassSpan = persistentClass.SubclassSpan + 1;
			subclassClosure = new string[subclassSpan];
			subclassClosure[0] = EntityName;
			if (persistentClass.IsPolymorphic)
				subclassesByDiscriminatorValue[discriminatorValue] = EntityName;

			#endregion

			#region SUBCLASSES
			if (persistentClass.IsPolymorphic)
			{
				int k = 1;
				foreach (Subclass sc in persistentClass.SubclassIterator)
				{
					subclassClosure[k++] = sc.EntityName;
					if (sc.IsDiscriminatorValueNull)
					{
						subclassesByDiscriminatorValue[NullDiscriminator] = sc.EntityName;
					}
					else if (sc.IsDiscriminatorValueNotNull)
					{
						subclassesByDiscriminatorValue[NotNullDiscriminator] = sc.EntityName;
					}
					else
					{
						if (discriminatorType == null)
							throw new MappingException("Not available discriminator type of entity " + persistentClass.EntityName);
						try
						{
							IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
							subclassesByDiscriminatorValue[dtype.StringToObject(sc.DiscriminatorValue)] = sc.EntityName;
						}
						catch (InvalidCastException cce)
						{
							throw new MappingException(
								string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
						}
						catch (Exception e)
						{
							throw new MappingException("Error parsing discriminator value of entity " + persistentClass.EntityName, e);
						}
					}
				}
			}

			#endregion

			InitLockers();

			InitSubclassPropertyAliasesMap(persistentClass);

			PostConstruct(mapping);
		}
Пример #46
0
		private void DoTestMinValueTimestampOnStrategy(ICache cache, ICacheConcurrencyStrategy strategy)
		{
			CacheKey key = CreateCacheKey("key");
			strategy.Cache = cache;
			strategy.Put(key, "value", long.MinValue, 0, null, false);

			Assert.IsNull(strategy.Get(key, long.MinValue), "{0} strategy fails the test", strategy.GetType());
			Assert.IsNull(strategy.Get(key, long.MaxValue), "{0} strategy fails the test", strategy.GetType());
		}
        public UnionSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
                                            ISessionFactoryImplementor factory, IMapping mapping) : base(persistentClass, cache, factory)
        {
            if (IdentifierGenerator is IdentityGenerator)
            {
                throw new MappingException("Cannot use identity column key generation with <union-subclass> mapping for: " + EntityName);
            }

            // TABLE

            var dialect            = factory.Dialect;
            var defaultCatalogName = factory.Settings.DefaultCatalogName;
            var defaultSchemaName  = factory.Settings.DefaultSchemaName;

            tableName = persistentClass.Table.GetQualifiedName(dialect, defaultCatalogName, defaultSchemaName);

            #region Custom SQL

            SqlString sql;
            bool      callable;
            ExecuteUpdateResultCheckStyle checkStyle;

            sql        = persistentClass.CustomSQLInsert;
            callable   = sql != null && persistentClass.IsCustomInsertCallable;
            checkStyle = sql == null
                                                        ? ExecuteUpdateResultCheckStyle.Count
                                                        : (persistentClass.CustomSQLInsertCheckStyle
                                                           ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable));
            customSQLInsert         = new SqlString[] { sql };
            insertCallable          = new bool[] { callable };
            insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle };

            sql        = persistentClass.CustomSQLUpdate;
            callable   = sql != null && persistentClass.IsCustomUpdateCallable;
            checkStyle = sql == null
                                                        ? ExecuteUpdateResultCheckStyle.Count
                                                        : (persistentClass.CustomSQLUpdateCheckStyle
                                                           ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable));
            customSQLUpdate         = new SqlString[] { sql };
            updateCallable          = new bool[] { callable };
            updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle };

            sql        = persistentClass.CustomSQLDelete;
            callable   = sql != null && persistentClass.IsCustomDeleteCallable;
            checkStyle = sql == null
                                                        ? ExecuteUpdateResultCheckStyle.Count
                                                        : (persistentClass.CustomSQLDeleteCheckStyle
                                                           ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable));
            customSQLDelete         = new SqlString[] { sql };
            deleteCallable          = new bool[] { callable };
            deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle };

            #endregion

            discriminatorValue    = persistentClass.SubclassId;
            discriminatorSQLValue = persistentClass.SubclassId.ToString();

            #region PROPERTIES

            int subclassSpan = persistentClass.SubclassSpan + 1;
            subclassClosure    = new string[subclassSpan];
            subclassClosure[0] = EntityName;

            #endregion

            #region SUBCLASSES

            subclassByDiscriminatorValue[persistentClass.SubclassId] = persistentClass.EntityName;
            if (persistentClass.IsPolymorphic)
            {
                int k = 1;
                foreach (Subclass sc in persistentClass.SubclassIterator)
                {
                    subclassClosure[k++] = sc.EntityName;
                    subclassByDiscriminatorValue[sc.SubclassId] = sc.EntityName;
                }
            }

            #endregion

            #region SPACES
            //TODO: i'm not sure, but perhaps we should exclude abstract denormalized tables?

            int spacesSize = 1 + persistentClass.SynchronizedTables.Count;
            spaces    = new string[spacesSize];
            spaces[0] = tableName;
            IEnumerator <string> iSyncTab = persistentClass.SynchronizedTables.GetEnumerator();
            for (int i = 1; i < spacesSize; i++)
            {
                iSyncTab.MoveNext();
                spaces[i] = iSyncTab.Current;
            }

            subclassSpaces = persistentClass.SubclassTableClosureIterator
                             .Select(table =>
                                     table.GetQualifiedName(dialect, defaultCatalogName, defaultSchemaName))
                             .Distinct().ToArray();

            subquery = GenerateSubquery(persistentClass, mapping);

            if (IsMultiTable)
            {
                var tableNames = new List <string>();
                var keyColumns = new List <string[]>();
                if (!IsAbstract)
                {
                    tableNames.Add(tableName);
                    keyColumns.Add(IdentifierColumnNames);
                }
                foreach (var tab in persistentClass.SubclassTableClosureIterator)
                {
                    if (!tab.IsAbstractUnionTable)
                    {
                        string _tableName =
                            tab.GetQualifiedName(dialect, defaultCatalogName, defaultSchemaName);
                        tableNames.Add(_tableName);

                        var names = tab.PrimaryKey.ColumnIterator
                                    .Select(column => column.GetQuotedName(dialect))
                                    .ToArray();

                        keyColumns.Add(names);
                    }
                }

                constraintOrderedTableNames     = tableNames.ToArray();
                constraintOrderedKeyColumnNames = keyColumns.ToArray();
            }
            else
            {
                constraintOrderedTableNames     = new string[] { tableName };
                constraintOrderedKeyColumnNames = new string[][] { IdentifierColumnNames };
            }
            #endregion

            InitLockers();

            InitSubclassPropertyAliasesMap(persistentClass);

            PostConstruct(mapping);
        }
		public CustomPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory,
													 IMapping mapping)
		{
			this.factory = factory;
		}
		protected AbstractEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
																			ISessionFactoryImplementor factory)
		{
			this.factory = factory;
			this.cache = cache;
			isLazyPropertiesCacheable = persistentClass.IsLazyPropertiesCacheable;
			cacheEntryStructure = factory.Settings.IsStructuredCacheEntriesEnabled
															? (ICacheEntryStructure)new StructuredCacheEntry(this)
															: (ICacheEntryStructure)new UnstructuredCacheEntry();

			entityMetamodel = new EntityMetamodel(persistentClass, factory);

			if (persistentClass.HasPocoRepresentation)
			{
				//TODO: this is currently specific to pojos, but need to be available for all entity-modes
				foreach (Subclass subclass in persistentClass.SubclassIterator)
				{
					entityNameBySubclass[subclass.MappedClass] = subclass.EntityName;
				}
			}

			batchSize = persistentClass.BatchSize.HasValue ? persistentClass.BatchSize.Value : factory.Settings.DefaultBatchFetchSize;
			hasSubselectLoadableCollections = persistentClass.HasSubselectLoadableCollections;

			propertyMapping = new BasicEntityPropertyMapping(this);

			#region IDENTIFIER

			identifierColumnSpan = persistentClass.Identifier.ColumnSpan;
			rootTableKeyColumnNames = new string[identifierColumnSpan];
			identifierAliases = new string[identifierColumnSpan];

			rowIdName = persistentClass.RootTable.RowId;

			loaderName = persistentClass.LoaderName;

			// TODO NH: Not safe cast to Column
			int i = 0;
			foreach (Column col in persistentClass.Identifier.ColumnIterator)
			{
				rootTableKeyColumnNames[i] = col.GetQuotedName(factory.Dialect);
				identifierAliases[i] = col.GetAlias(factory.Dialect, persistentClass.RootTable);
				i++;
			}

			#endregion

			#region VERSION

			if (persistentClass.IsVersioned)
			{
				foreach (Column col in persistentClass.Version.ColumnIterator)
				{
					versionColumnName = col.GetQuotedName(factory.Dialect);
					break; //only happens once
				}
			}
			else
			{
				versionColumnName = null;
			}

			#endregion

			#region WHERE STRING

			sqlWhereString = !string.IsNullOrEmpty(persistentClass.Where) ? "( " + persistentClass.Where + ") " : null;
			sqlWhereStringTemplate = sqlWhereString == null
																? null
																: Template.RenderWhereStringTemplate(sqlWhereString, factory.Dialect,
																																		 factory.SQLFunctionRegistry);

			#endregion

			#region PROPERTIES

			// NH: see consistence with the implementation on EntityMetamodel where we are disabling lazy-properties for no lazy entities
			bool lazyAvailable = IsInstrumented(EntityMode.Poco) && entityMetamodel.IsLazy;

			int hydrateSpan = entityMetamodel.PropertySpan;
			propertyColumnSpans = new int[hydrateSpan];
			propertySubclassNames = new string[hydrateSpan];
			propertyColumnAliases = new string[hydrateSpan][];
			propertyColumnNames = new string[hydrateSpan][];
			propertyColumnFormulaTemplates = new string[hydrateSpan][];
			propertyUniqueness = new bool[hydrateSpan];
			propertySelectable = new bool[hydrateSpan];
			propertyColumnUpdateable = new bool[hydrateSpan][];
			propertyColumnInsertable = new bool[hydrateSpan][];
			var thisClassProperties = new HashSet<Property>();

			lazyProperties = new HashedSet<string>();
			List<string> lazyNames = new List<string>();
			List<int> lazyNumbers = new List<int>();
			List<IType> lazyTypes = new List<IType>();
			List<string[]> lazyColAliases = new List<string[]>();

			i = 0;
			bool foundFormula = false;
			foreach (Property prop in persistentClass.PropertyClosureIterator)
			{
				thisClassProperties.Add(prop);

				int span = prop.ColumnSpan;
				propertyColumnSpans[i] = span;
				propertySubclassNames[i] = prop.PersistentClass.EntityName;
				string[] colNames = new string[span];
				string[] colAliases = new string[span];
				string[] templates = new string[span];
				int k = 0;
				foreach (ISelectable thing in prop.ColumnIterator)
				{
					colAliases[k] = thing.GetAlias(factory.Dialect, prop.Value.Table);
					if (thing.IsFormula)
					{
						foundFormula = true;
						templates[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
					}
					else
					{
						colNames[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
					}
					k++;
				}
				propertyColumnNames[i] = colNames;
				propertyColumnFormulaTemplates[i] = templates;
				propertyColumnAliases[i] = colAliases;

				if (lazyAvailable && prop.IsLazy)
				{
					lazyProperties.Add(prop.Name);
					lazyNames.Add(prop.Name);
					lazyNumbers.Add(i);
					lazyTypes.Add(prop.Value.Type);
					lazyColAliases.Add(colAliases);
				}

				propertyColumnUpdateable[i] = prop.Value.ColumnUpdateability;
				propertyColumnInsertable[i] = prop.Value.ColumnInsertability;

				propertySelectable[i] = prop.IsSelectable;

				propertyUniqueness[i] = prop.Value.IsAlternateUniqueKey;

				i++;
			}
			hasFormulaProperties = foundFormula;
			lazyPropertyColumnAliases = lazyColAliases.ToArray();
			lazyPropertyNames = lazyNames.ToArray();
			lazyPropertyNumbers = lazyNumbers.ToArray();
			lazyPropertyTypes = lazyTypes.ToArray();

			#endregion

			#region SUBCLASS PROPERTY CLOSURE

			List<string> columns = new List<string>();
			List<bool> columnsLazy = new List<bool>();
			List<string> aliases = new List<string>();
			List<string> formulas = new List<string>();
			List<string> formulaAliases = new List<string>();
			List<string> formulaTemplates = new List<string>();
			List<bool> formulasLazy = new List<bool>();
			List<IType> types = new List<IType>();
			List<string> names = new List<string>();
			List<string> classes = new List<string>();
			List<string[]> templates2 = new List<string[]>();
			List<string[]> propColumns = new List<string[]>();
			List<FetchMode> joinedFetchesList = new List<FetchMode>();
			List<CascadeStyle> cascades = new List<CascadeStyle>();
			List<bool> definedBySubclass = new List<bool>();
			List<int[]> propColumnNumbers = new List<int[]>();
			List<int[]> propFormulaNumbers = new List<int[]>();
			List<bool> columnSelectables = new List<bool>();
			List<bool> propNullables = new List<bool>();

			foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
			{
				names.Add(prop.Name);
				classes.Add(prop.PersistentClass.EntityName);
				bool isDefinedBySubclass = !thisClassProperties.Contains(prop);
				definedBySubclass.Add(isDefinedBySubclass);
				propNullables.Add(prop.IsOptional || isDefinedBySubclass); //TODO: is this completely correct?
				types.Add(prop.Type);

				string[] cols = new string[prop.ColumnSpan];
				string[] forms = new string[prop.ColumnSpan];
				int[] colnos = new int[prop.ColumnSpan];
				int[] formnos = new int[prop.ColumnSpan];
				int l = 0;
				bool lazy = prop.IsLazy && lazyAvailable;
				foreach (ISelectable thing in prop.ColumnIterator)
				{
					if (thing.IsFormula)
					{
						string template = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
						formnos[l] = formulaTemplates.Count;
						colnos[l] = -1;
						formulaTemplates.Add(template);
						forms[l] = template;
						formulas.Add(thing.GetText(factory.Dialect));
						formulaAliases.Add(thing.GetAlias(factory.Dialect));
						formulasLazy.Add(lazy);
					}
					else
					{
						string colName = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
						colnos[l] = columns.Count; //before add :-)
						formnos[l] = -1;
						columns.Add(colName);
						cols[l] = colName;
						aliases.Add(thing.GetAlias(factory.Dialect, prop.Value.Table));
						columnsLazy.Add(lazy);
						columnSelectables.Add(prop.IsSelectable);
					}
					l++;
				}
				propColumns.Add(cols);
				templates2.Add(forms);
				propColumnNumbers.Add(colnos);
				propFormulaNumbers.Add(formnos);

				joinedFetchesList.Add(prop.Value.FetchMode);
				cascades.Add(prop.CascadeStyle);
			}
			subclassColumnClosure = columns.ToArray();
			subclassColumnAliasClosure = aliases.ToArray();
			subclassColumnLazyClosure = columnsLazy.ToArray();
			subclassColumnSelectableClosure = columnSelectables.ToArray();

			subclassFormulaClosure = formulas.ToArray();
			subclassFormulaTemplateClosure = formulaTemplates.ToArray();
			subclassFormulaAliasClosure = formulaAliases.ToArray();
			subclassFormulaLazyClosure = formulasLazy.ToArray();

			subclassPropertyNameClosure = names.ToArray();
			subclassPropertySubclassNameClosure = classes.ToArray();
			subclassPropertyTypeClosure = types.ToArray();
			subclassPropertyNullabilityClosure = propNullables.ToArray();
			subclassPropertyFormulaTemplateClosure = templates2.ToArray();
			subclassPropertyColumnNameClosure = propColumns.ToArray();
			subclassPropertyColumnNumberClosure = propColumnNumbers.ToArray();
			subclassPropertyFormulaNumberClosure = propFormulaNumbers.ToArray();

			subclassPropertyCascadeStyleClosure = cascades.ToArray();
			subclassPropertyFetchModeClosure = joinedFetchesList.ToArray();

			propertyDefinedOnSubclass = definedBySubclass.ToArray();

			#endregion

			// Handle any filters applied to the class level
			filterHelper = new FilterHelper(persistentClass.FilterMap, factory.Dialect, factory.SQLFunctionRegistry);

			temporaryIdTableName = persistentClass.TemporaryIdTableName;
			temporaryIdTableDDL = persistentClass.TemporaryIdTableDDL;
		}
		public AbstractCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache,
		                                   ISessionFactoryImplementor factory)
		{
			this.factory = factory;
			dialect = factory.Dialect;
			this.cache = cache;
			//sqlExceptionConverter = factory.SQLExceptionConverter;
			collectionType = collection.CollectionType;
			role = collection.Role;
			ownerClass = collection.OwnerClass;
			ownerPersister = factory.GetEntityPersister(ownerClass);
			queryLoaderName = collection.LoaderName;
			Alias alias = new Alias("__");

			sqlOrderByString = collection.OrderBy;
			hasOrder = sqlOrderByString != null;
			sqlOrderByStringTemplate = hasOrder
			                           	? Template.RenderOrderByStringTemplate(sqlOrderByString, dialect,
			                           	                                       factory.SQLFunctionRegistry) : null;

			sqlWhereString = collection.Where;
			hasWhere = sqlWhereString != null;
			sqlWhereStringTemplate = hasWhere
			                         	? Template.RenderWhereStringTemplate(sqlWhereString, dialect, factory.SQLFunctionRegistry)
			                         	: null;

			hasOrphanDelete = collection.OrphanDelete;

			batchSize = collection.BatchSize;
			isVersioned = collection.IsOptimisticLocked;

			keyType = collection.Key.Type;
			int keySpan = collection.Key.ColumnSpan;
			keyColumnNames = new string[keySpan];
			string[] keyAliases = new string[keySpan];
			int k = 0;
			foreach (Column col in collection.Key.ColumnCollection)
			{
				keyColumnNames[k] = col.GetQuotedName(dialect);
				keyAliases[k] = col.GetAlias(dialect);
				k++;
			}
			keyColumnAliases = alias.ToAliasStrings(keyAliases, dialect);
			//unquotedKeyColumnNames = StringHelper.Unquote( keyColumnAliases );
			ISet distinctColumns = new HashedSet();
			CheckColumnDuplication(distinctColumns, collection.Key.ColumnCollection);

			//isSet = collection.IsSet;
			//isSorted = collection.IsSorted;
			primitiveArray = collection.IsPrimitiveArray;
			array = collection.IsArray;
			subselectLoadable = collection.IsSubselectLoadable;

			IValue element = collection.Element;
			int elementSpan = element.ColumnSpan;
			Table table = collection.CollectionTable;
			fetchMode = element.FetchMode;
			elementType = element.Type;

			if (!collection.IsOneToMany)
			{
				CheckColumnDuplication(distinctColumns, element.ColumnCollection);
			}

			if (elementType.IsEntityType)
			{
				elementPersister = factory.GetEntityPersister(((EntityType) elementType).AssociatedClass);
			}
			else
			{
				elementPersister = null;
			}

			qualifiedTableName = table.GetQualifiedName(dialect, factory.DefaultSchema);
			elementColumnAliases = new string[elementSpan];
			elementColumnNames = new string[elementSpan];
			elementFormulaTemplates = new string[elementSpan];
			elementFormulas = new string[elementSpan];
			elementColumnIsSettable = new bool[elementSpan];
			elementColumnIsInPrimaryKey = new bool[elementSpan];
			int j = 0;
			foreach (ISelectable selectable in element.ColumnCollection)
			{
				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;
				}
				j++;
			}

			hasIndex = collection.IsIndexed;

			if (hasIndex)
			{
				IndexedCollection indexedCollection = (IndexedCollection) collection;

				indexType = indexedCollection.Index.Type;
				int indexSpan = indexedCollection.Index.ColumnSpan;
				indexColumnNames = new string[indexSpan];

				string[] indexAliases = new string[indexSpan];
				int i = 0;
				foreach (Column indexCol in indexedCollection.Index.ColumnCollection)
				{
					indexAliases[i] = indexCol.GetAlias(dialect);
					indexColumnNames[i] = indexCol.GetQuotedName(dialect);
					i++;
				}
				indexColumnAliases = alias.ToAliasStrings(indexAliases, dialect);
				CheckColumnDuplication(distinctColumns, indexedCollection.Index.ColumnCollection);
			}
			else
			{
				indexType = null;
				indexColumnNames = null;
				indexColumnAliases = 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.ColumnCollection)
				{
					col = column;
					break;
				}

				identifierColumnName = col.GetQuotedName(dialect);
				identifierColumnAlias = alias.ToAliasString(col.GetAlias(dialect), dialect);
				identifierGenerator = idColl.Identifier.CreateIdentifierGenerator(dialect);
				CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnCollection);
			}
			else
			{
				identifierType = null;
				identifierColumnName = null;
				identifierColumnAlias = null;
				identifierGenerator = null;
			}

			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 == null
				                   	? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLInsert, insertCallable)
				                   	: collection.CustomSQLInsertCheckStyle;
			}

			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 == null
				                   	? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLUpdate, updateCallable)
				                   	: collection.CustomSQLUpdateCheckStyle;
			}

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

			isLazy = collection.IsLazy;

			isInverse = collection.IsInverse;

			if (collection.IsArray)
			{
				elementClass = ((Array) collection).ElementClass;
			}
			else
			{
				// for non-arrays, we don't need to know the element class
				elementClass = null;
			}

			if (elementType.IsComponentType)
			{
				elementPropertyMapping = new CompositeElementPropertyMapping(
					elementColumnNames, elementFormulaTemplates,
					(IAbstractComponentType) elementType, factory);
			}
			else if (!elementType.IsEntityType)
			{
				elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType);
			}
			else
			{
				IEntityPersister persister = factory.GetEntityPersister(((EntityType) elementType).AssociatedClass);
				// Not all classpersisters implement IPropertyMapping!
				if (persister is IPropertyMapping)
				{
					elementPropertyMapping = (IPropertyMapping) persister;
				}
				else
				{
					elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType);
				}
			}

			// Handle any filters applied to this collection
			filterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry);

			// Handle any filters applied to this collection for many-to-many
			manyToManyFilterHelper = new FilterHelper(collection.ManyToManyFilterMap, dialect, factory.SQLFunctionRegistry);
			manyToManyWhereString = StringHelper.IsNotEmpty(collection.ManyToManyWhere) ?
			                        "( " + collection.ManyToManyWhere + " )" :
			                        null;
			manyToManyWhereTemplate = manyToManyWhereString == null
			                          	?
			                          null
			                          	:
			                          Template.RenderWhereStringTemplate(manyToManyWhereString, factory.Dialect,
			                                                             factory.SQLFunctionRegistry);
				// , factory.getSqlFunctionRegistry() );
			manyToManyOrderByString = collection.ManyToManyOrdering;
			manyToManyOrderByTemplate = manyToManyOrderByString == null
			                            	? null
			                            	: Template.RenderOrderByStringTemplate(manyToManyOrderByString, factory.Dialect,
			                            	                                       factory.SQLFunctionRegistry);
				// , factory.getSqlFunctionRegistry() );

			InitCollectionPropertyMap();
		}
		internal void SetCacheConcurrencyStrategy( System.Type clazz, ICacheConcurrencyStrategy concurrencyStrategy, string region )
		{
			RootClass rootClass = GetRootClassMapping( clazz );
			rootClass.Cache = concurrencyStrategy;
			caches[ rootClass.MappedClass.FullName ] = concurrencyStrategy;
		}
 public MyCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) : base(collection, cache, factory)
 {
 }
		internal void SetCacheConcurrencyStrategy( string collectionRole, ICacheConcurrencyStrategy concurrencyStrategy, string region )
		{
			// TODO: this is ported from H2.1.8, but the implementation looks
			// very strange to me - region parameter is ignored,
			// collection.Role is used instead of collectionRole, etc.
			NHibernate.Mapping.Collection collection = GetCollectionMapping( collectionRole );
			collection.Cache = concurrencyStrategy;
			if( caches.Contains( collection.Role ) )
			{
				throw new MappingException( "duplicate cache region " + collection.Role );
			}
			caches.Add( collection.Role, concurrencyStrategy );
		}
        public SingleTableEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
                                          ISessionFactoryImplementor factory, IMapping mapping)
            : base(persistentClass, cache, factory)
        {
            #region CLASS + TABLE

            joinSpan            = persistentClass.JoinClosureSpan + 1;
            qualifiedTableNames = new string[joinSpan];
            isInverseTable      = new bool[joinSpan];
            isNullableTable     = new bool[joinSpan];
            keyColumnNames      = new string[joinSpan][];
            Table table = persistentClass.RootTable;
            qualifiedTableNames[0] =
                table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
            isInverseTable[0]    = false;
            isNullableTable[0]   = false;
            keyColumnNames[0]    = IdentifierColumnNames;
            cascadeDeleteEnabled = new bool[joinSpan];

            // Custom sql
            customSQLInsert         = new SqlString[joinSpan];
            customSQLUpdate         = new SqlString[joinSpan];
            customSQLDelete         = new SqlString[joinSpan];
            insertCallable          = new bool[joinSpan];
            updateCallable          = new bool[joinSpan];
            deleteCallable          = new bool[joinSpan];
            insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
            updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
            deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];

            customSQLInsert[0]         = persistentClass.CustomSQLInsert;
            insertCallable[0]          = customSQLInsert[0] != null && persistentClass.IsCustomInsertCallable;
            insertResultCheckStyles[0] = persistentClass.CustomSQLInsertCheckStyle
                                         ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0]);
            customSQLUpdate[0]         = persistentClass.CustomSQLUpdate;
            updateCallable[0]          = customSQLUpdate[0] != null && persistentClass.IsCustomUpdateCallable;
            updateResultCheckStyles[0] = persistentClass.CustomSQLUpdateCheckStyle
                                         ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0]);
            customSQLDelete[0]         = persistentClass.CustomSQLDelete;
            deleteCallable[0]          = customSQLDelete[0] != null && persistentClass.IsCustomDeleteCallable;
            deleteResultCheckStyles[0] = persistentClass.CustomSQLDeleteCheckStyle
                                         ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0]);

            #endregion

            #region JOINS
            int j = 1;
            foreach (Join join in persistentClass.JoinClosureIterator)
            {
                qualifiedTableNames[j]  = join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                isInverseTable[j]       = join.IsInverse;
                isNullableTable[j]      = join.IsOptional;
                cascadeDeleteEnabled[j] = join.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete;

                customSQLInsert[j]         = join.CustomSQLInsert;
                insertCallable[j]          = customSQLInsert[j] != null && join.IsCustomInsertCallable;
                insertResultCheckStyles[j] = join.CustomSQLInsertCheckStyle
                                             ??
                                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[j], insertCallable[j]);
                customSQLUpdate[j]         = join.CustomSQLUpdate;
                updateCallable[j]          = customSQLUpdate[j] != null && join.IsCustomUpdateCallable;
                updateResultCheckStyles[j] = join.CustomSQLUpdateCheckStyle
                                             ??
                                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[j], updateCallable[j]);
                customSQLDelete[j]         = join.CustomSQLDelete;
                deleteCallable[j]          = customSQLDelete[j] != null && join.IsCustomDeleteCallable;
                deleteResultCheckStyles[j] = join.CustomSQLDeleteCheckStyle
                                             ??
                                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[j], deleteCallable[j]);

                IEnumerable <Column> enumerableKeyCol = new SafetyEnumerable <Column>(join.Key.ColumnIterator);
                List <string>        kcName           = new List <string>(join.Key.ColumnSpan);
                foreach (Column col in enumerableKeyCol)
                {
                    kcName.Add(col.GetQuotedName(factory.Dialect));
                }

                keyColumnNames[j] = kcName.ToArray();

                j++;
            }

            constraintOrderedTableNames     = new string[qualifiedTableNames.Length];
            constraintOrderedKeyColumnNames = new string[qualifiedTableNames.Length][];
            for (int i = qualifiedTableNames.Length - 1, position = 0; i >= 0; i--, position++)
            {
                constraintOrderedTableNames[position]     = qualifiedTableNames[i];
                constraintOrderedKeyColumnNames[position] = keyColumnNames[i];
            }

            spaces = ArrayHelper.Join(qualifiedTableNames, ArrayHelper.ToStringArray(persistentClass.SynchronizedTables));

            bool lazyAvailable = IsInstrumented(EntityMode.Poco);

            bool            hasDeferred    = false;
            List <string>   subclassTables = new List <string>();
            List <string[]> joinKeyColumns = new List <string[]>();
            List <bool>     isConcretes    = new List <bool>();
            List <bool>     isDeferreds    = new List <bool>();
            List <bool>     isInverses     = new List <bool>();
            List <bool>     isNullables    = new List <bool>();
            List <bool>     isLazies       = new List <bool>();
            subclassTables.Add(qualifiedTableNames[0]);
            joinKeyColumns.Add(IdentifierColumnNames);
            isConcretes.Add(true);
            isDeferreds.Add(false);
            isInverses.Add(false);
            isNullables.Add(false);
            isLazies.Add(false);
            foreach (Join join in persistentClass.SubclassJoinClosureIterator)
            {
                isConcretes.Add(persistentClass.IsClassOrSuperclassJoin(join));
                isDeferreds.Add(join.IsSequentialSelect);
                isInverses.Add(join.IsInverse);
                isNullables.Add(join.IsOptional);
                isLazies.Add(lazyAvailable && join.IsLazy);
                if (join.IsSequentialSelect && !persistentClass.IsClassOrSuperclassJoin(join))
                {
                    hasDeferred = true;
                }
                subclassTables.Add(join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName));
                IEnumerable <Column> enumerableKeyCol = new SafetyEnumerable <Column>(join.Key.ColumnIterator);
                List <string>        keyCols          = new List <string>(join.Key.ColumnSpan);
                foreach (Column col in enumerableKeyCol)
                {
                    keyCols.Add(col.GetQuotedName(factory.Dialect));
                }

                joinKeyColumns.Add(keyCols.ToArray());
            }

            subclassTableSequentialSelect = isDeferreds.ToArray();
            subclassTableNameClosure      = subclassTables.ToArray();
            subclassTableIsLazyClosure    = isLazies.ToArray();
            subclassTableKeyColumnClosure = joinKeyColumns.ToArray();
            isClassOrSuperclassTable      = isConcretes.ToArray();
            isInverseSubclassTable        = isInverses.ToArray();
            isNullableSubclassTable       = isNullables.ToArray();
            hasSequentialSelects          = hasDeferred;

            #endregion

            #region DISCRIMINATOR

            if (persistentClass.IsPolymorphic)
            {
                IValue discrimValue = persistentClass.Discriminator;
                if (discrimValue == null)
                {
                    throw new MappingException("Discriminator mapping required for single table polymorphic persistence");
                }

                forceDiscriminator = persistentClass.IsForceDiscriminator;
                IEnumerator <ISelectable> iSel = discrimValue.ColumnIterator.GetEnumerator();
                iSel.MoveNext();
                ISelectable selectable = iSel.Current;
                if (discrimValue.HasFormula)
                {
                    Formula formula = (Formula)selectable;
                    discriminatorFormula         = formula.FormulaString;
                    discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
                    discriminatorColumnName      = null;
                    discriminatorAlias           = Discriminator_Alias;
                }
                else
                {
                    Column column = (Column)selectable;
                    discriminatorColumnName      = column.GetQuotedName(factory.Dialect);
                    discriminatorAlias           = column.GetAlias(factory.Dialect, persistentClass.RootTable);
                    discriminatorFormula         = null;
                    discriminatorFormulaTemplate = null;
                }
                discriminatorType = persistentClass.Discriminator.Type;
                if (persistentClass.IsDiscriminatorValueNull)
                {
                    discriminatorValue      = NullDiscriminator;
                    discriminatorSQLValue   = InFragment.Null;
                    discriminatorInsertable = false;
                }
                else if (persistentClass.IsDiscriminatorValueNotNull)
                {
                    discriminatorValue      = NotNullDiscriminator;
                    discriminatorSQLValue   = InFragment.NotNull;
                    discriminatorInsertable = false;
                }
                else
                {
                    discriminatorInsertable = persistentClass.IsDiscriminatorInsertable && !discrimValue.HasFormula;
                    try
                    {
                        IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
                        discriminatorValue    = dtype.StringToObject(persistentClass.DiscriminatorValue);
                        discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue, factory.Dialect);
                    }
                    catch (InvalidCastException cce)
                    {
                        throw new MappingException(
                                  string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
                    }
                    catch (Exception e)
                    {
                        throw new MappingException("Could not format discriminator value to SQL string of entity " + persistentClass.EntityName, e);
                    }
                }
            }
            else
            {
                forceDiscriminator           = false;
                discriminatorInsertable      = false;
                discriminatorColumnName      = null;
                discriminatorAlias           = null;
                discriminatorType            = null;
                discriminatorValue           = null;
                discriminatorSQLValue        = null;
                discriminatorFormula         = null;
                discriminatorFormulaTemplate = null;
            }

            #endregion

            #region PROPERTIES

            propertyTableNumbers = new int[PropertySpan];
            int i2 = 0;
            foreach (Property prop in persistentClass.PropertyClosureIterator)
            {
                propertyTableNumbers[i2++] = persistentClass.GetJoinNumber(prop);
            }

            List <int> columnJoinNumbers    = new List <int>();
            List <int> formulaJoinedNumbers = new List <int>();
            List <int> propertyJoinNumbers  = new List <int>();
            foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
            {
                int join = persistentClass.GetJoinNumber(prop);
                propertyJoinNumbers.Add(join);

                //propertyTableNumbersByName.put( prop.getName(), join );
                propertyTableNumbersByNameAndSubclass[prop.PersistentClass.EntityName + '.' + prop.Name] = join;
                foreach (ISelectable thing in prop.ColumnIterator)
                {
                    if (thing.IsFormula)
                    {
                        formulaJoinedNumbers.Add(join);
                    }
                    else
                    {
                        columnJoinNumbers.Add(join);
                    }
                }
            }

            subclassColumnTableNumberClosure   = columnJoinNumbers.ToArray();
            subclassFormulaTableNumberClosure  = formulaJoinedNumbers.ToArray();
            subclassPropertyTableNumberClosure = propertyJoinNumbers.ToArray();

            int subclassSpan = persistentClass.SubclassSpan + 1;
            subclassClosure    = new string[subclassSpan];
            subclassClosure[0] = EntityName;
            if (persistentClass.IsPolymorphic)
            {
                subclassesByDiscriminatorValue[discriminatorValue] = EntityName;
            }

            #endregion

            #region SUBCLASSES
            if (persistentClass.IsPolymorphic)
            {
                int k = 1;
                foreach (Subclass sc in persistentClass.SubclassIterator)
                {
                    subclassClosure[k++] = sc.EntityName;
                    if (sc.IsDiscriminatorValueNull)
                    {
                        subclassesByDiscriminatorValue[NullDiscriminator] = sc.EntityName;
                    }
                    else if (sc.IsDiscriminatorValueNotNull)
                    {
                        subclassesByDiscriminatorValue[NotNullDiscriminator] = sc.EntityName;
                    }
                    else
                    {
                        if (discriminatorType == null)
                        {
                            throw new MappingException("Not available discriminator type of entity " + persistentClass.EntityName);
                        }
                        try
                        {
                            IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
                            subclassesByDiscriminatorValue[dtype.StringToObject(sc.DiscriminatorValue)] = sc.EntityName;
                        }
                        catch (InvalidCastException cce)
                        {
                            throw new MappingException(
                                      string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
                        }
                        catch (Exception e)
                        {
                            throw new MappingException("Error parsing discriminator value of entity " + persistentClass.EntityName, e);
                        }
                    }
                }
            }

            #endregion

            InitLockers();

            InitSubclassPropertyAliasesMap(persistentClass);

            PostConstruct(mapping);
        }