/// <summary>
        /// 生成主键
        /// </summary>
        /// <param name="session"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public object Generate(ISessionImplementor session, object obj)
        {
            TypedEntityMetadata entityInfo = TypedEntityMetadata.GenerateEntityInfo(session.Factory, obj.GetType());

            return PrimaryMaxIdGenerator.GetMaxId(entityInfo.TableName, entityInfo.IdColumnName, entityInfo.IdLength,
                PrimaryMaxIdGenerator.GetIdYearMonth()).ToString();
        }
        public override INHibernateProxy GetProxy(object id, ISessionImplementor session)
        {
            // If it is not a proxy for a class do what you usually did.
            if (!IsClassProxy) return base.GetProxy(id, session);

            try
            {
                LazyInitializer initializer = new DataBindingInterceptor(EntityName, PersistentClass, id,
                           GetIdentifierMethod, SetIdentifierMethod, ComponentIdType, session);

                // Add to the list of the interfaces that the proxy class will support the INotifyPropertyChanged interface.
                // This is only needed in the case when we need to cast our proxy object as INotifyPropertyChanged interface.
                ArrayList list = new ArrayList(Interfaces);
                list.Add(typeof(INotifyPropertyChanged));
                System.Type[] interfaces = (System.Type[])list.ToArray(typeof(System.Type));

                //We create the proxy
                object generatedProxy = DefaultProxyGenerator.CreateClassProxy(PersistentClass, interfaces, initializer);

                initializer._constructed = true;
                return (INHibernateProxy)generatedProxy;
            }
            catch (Exception e)
            {
                Logger.Error("Creating a proxy instance failed", e);
                throw new HibernateException("Creating a proxy instance failed", e);
            }
        }
		public override object Assemble(object cached, ISessionImplementor session, object owner)
		{
			byte[] identifier = cached as byte[];
			if (identifier == null) return null;
			IExternalBlobConnection conn = GetExternalBlobConnection(session);
			return CreateLobInstance(conn, identifier);
		}
Ejemplo n.º 4
0
		public object Load(object id, object optionalObject, ISessionImplementor session)
		{
			object[] batch = session.PersistenceContext.BatchFetchQueue.GetEntityBatch(persister, id, batchSizes[0]);

			for (int i = 0; i < batchSizes.Length - 1; i++)
			{
				int smallBatchSize = batchSizes[i];
				if (batch[smallBatchSize - 1] != null)
				{
					object[] smallBatch = new object[smallBatchSize];
					Array.Copy(batch, 0, smallBatch, 0, smallBatchSize);

					IList results = loaders[i].LoadEntityBatch(
						session,
						smallBatch,
						idType,
						optionalObject,
						persister.EntityName,
						id,
						persister);

					return GetObjectFromList(results, id, session); //EARLY EXIT
				}
			}

			return ((IUniqueEntityLoader) loaders[batchSizes.Length - 1]).Load(id, optionalObject, session);
		}
Ejemplo n.º 5
0
		public IList Get(QueryKey key, ICacheAssembler[] returnTypes, Iesi.Collections.Generic.ISet<string> spaces, ISessionImplementor session)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("checking cached query results in region: " + regionName);
			}
			IList cacheable = (IList) queryCache.Get(key);
			if (cacheable == null)
			{
				log.Debug("query results were not found in cache");
				return null;
			}
			IList result = new ArrayList(cacheable.Count - 1);
			long timestamp = (long) cacheable[0];
			log.Debug("Checking query spaces for up-to-dateness [" + spaces + "]");
			if (! IsUpToDate(spaces, timestamp))
			{
				log.Debug("cached query results were not up to date");
				return null;
			}
			log.Debug("returning cached query results");
			for (int i = 1; i < cacheable.Count; i++)
			{
				if (returnTypes.Length == 1)
				{
					result.Add(returnTypes[0].Assemble(cacheable[i], session, null));
				}
				else
				{
					result.Add(TypeFactory.Assemble((object[]) cacheable[i], returnTypes, session, null));
				}
			}
			return result;
		}
		public EntityIdentityInsertAction(object[] state, object instance, IEntityPersister persister, ISessionImplementor session, bool isDelayed)
			: base(session, null, instance, persister)
		{
			this.state = state;
			this.isDelayed = isDelayed;
			delayedEntityKey = this.isDelayed ? GenerateDelayedEntityKey() : null;
		}
		public object Load( ISessionImplementor session, object id, object optionalObject, object optionalId )
		{
			IList list = LoadEntity( session, id, uniqueKeyType, optionalObject, optionalId );
			if( list.Count == 1 )
			{
				return list[ 0 ];
			}
			else if( list.Count == 0 )
			{
				return null;
			}
			else
			{
				if ( CollectionOwner > -1 )
				{
					return list[ 0 ];
				}
				else
				{
					throw new HibernateException(
						"More than one row with the given identifier was found: " +
						id +
						", for class: " +
						Persister.ClassName );
				}
			}
		}
		protected override Object GetResultColumnOrRow(
			Object[ ] row,
			IDataReader rs,
			ISessionImplementor session )
		{
			return row[ 0 ];
		}
Ejemplo n.º 9
0
		public bool Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, bool isNaturalKeyLookup, ISessionImplementor session)
		{
			if (isNaturalKeyLookup && result.Count == 0)
				return false;

			long ts = session.Timestamp;

			if (Log.IsDebugEnabled)
				Log.DebugFormat("caching query results in region: '{0}'; {1}", _regionName, key);

			IList cacheable = new List<object>(result.Count + 1) {ts};
			for (int i = 0; i < result.Count; i++)
			{
				if (returnTypes.Length == 1 && !key.HasResultTransformer)
				{
					cacheable.Add(returnTypes[0].Disassemble(result[i], session, null));
				}
				else
				{
					cacheable.Add(TypeHelper.Disassemble((object[]) result[i], returnTypes, null, session, null));
				}
			}

			_queryCache.Put(key, cacheable);

			return true;
		}
		/// <summary>
		/// Generate an <see cref="Int16"/>, <see cref="Int32"/>, or <see cref="Int64"/> 
		/// for the identifier by using a database sequence.
		/// </summary>
		/// <param name="session">The <see cref="ISessionImplementor"/> this id is being generated in.</param>
		/// <param name="obj">The entity for which the id is being generated.</param>
		/// <returns>The new identifier as a <see cref="Int16"/>, <see cref="Int32"/>, or <see cref="Int64"/>.</returns>
		public virtual object Generate( ISessionImplementor session, object obj )
		{
			IDbCommand cmd = session.Batcher.PrepareCommand( new SqlString( sql ) );
			IDataReader reader = null;
			try
			{
				reader = session.Batcher.ExecuteReader( cmd );
				object result = null;
				reader.Read();
				result = IdentifierGeneratorFactory.Get( reader, returnClass );

				log.Debug( "sequence ID generated: " + result );
				return result;
			} 
				// TODO: change to SQLException
			catch( Exception e )
			{
				// TODO: add code to log the sql exception
				log.Error( "error generating sequence", e );
				throw;
			}
			finally
			{
				session.Batcher.CloseCommand( cmd, reader );
			}
		}
		public EntityDeleteAction(object id, object[] state, object version, object instance, IEntityPersister persister, bool isCascadeDeleteEnabled, ISessionImplementor session)
			: base(session, id, instance, persister)
		{
			this.state = state;
			this.version = version;
			this.isCascadeDeleteEnabled = isCascadeDeleteEnabled;
		}
Ejemplo n.º 12
0
			public Nullifier(object self, bool isDelete, bool isEarlyInsert, ISessionImplementor session)
			{
				this.isDelete = isDelete;
				this.isEarlyInsert = isEarlyInsert;
				this.session = session;
				this.self = self;
			}
Ejemplo n.º 13
0
        protected virtual object Load(ISessionImplementor session, object id, object optionalObject, object optionalId)
        {
            IList list = LoadEntity(session, id, uniqueKeyType, optionalObject, entityName, optionalId, persister);

            if (list.Count == 1)
            {
                return list[0];
            }
            else if (list.Count == 0)
            {
                return null;
            }
            else
            {
                if (CollectionOwners != null)
                {
                    return list[0];
                }
                else
                {
                    throw new HibernateException(
                        string.Format("More than one row with the given identifier was found: {0}, for class: {1}", id,
                                      persister.EntityName));
                }
            }
        }
Ejemplo n.º 14
0
		public object Load(object id, object optionalObject, ISessionImplementor session)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug(string.Format("loading entity: {0} using named query: {1}", persister.EntityName, queryName));
			}

			AbstractQueryImpl query = (AbstractQueryImpl) session.GetNamedQuery(queryName);
			if (query.HasNamedParameters)
			{
				query.SetParameter(query.NamedParameters[0], id, persister.IdentifierType);
			}
			else
			{
				query.SetParameter(0, id, persister.IdentifierType);
			}
			query.SetOptionalId(id);
			query.SetOptionalEntityName(persister.EntityName);
			query.SetOptionalObject(optionalObject);
			query.SetFlushMode(FlushMode.Never);
			query.List();

			// now look up the object we are really interested in!
			// (this lets us correctly handle proxies and multi-row
			// or multi-column queries)
			return session.PersistenceContext.GetEntity(session.GenerateEntityKey(id, persister));
		}
		/// <summary>
		/// Disassembles the object into a cacheable representation.
		/// </summary>
		/// <param name="value">The value to disassemble.</param>
		/// <param name="session">The <see cref="ISessionImplementor"/> is not used by this method.</param>
		/// <param name="owner">optional parent entity object (needed for collections) </param>
		/// <returns>The disassembled, deep cloned state of the object</returns>
		/// <remarks>
		/// This method calls DeepCopy if the value is not null.
		/// </remarks>
		public virtual object Disassemble(object value, ISessionImplementor session, object owner)
		{
			if (value == null) 
				return null;

			return DeepCopy(value, session.EntityMode, session.Factory);
		}
Ejemplo n.º 16
0
        /// <summary>
        /// Generates an identifer from the value of a Property. 
        /// </summary>
        /// <param name="sessionImplementor">The <see cref="ISessionImplementor"/> this id is being generated in.</param>
        /// <param name="obj">The entity for which the id is being generated.</param>
        /// <returns>
        /// The identifier value from the associated object or  
        /// <see cref="IdentifierGeneratorFactory.ShortCircuitIndicator"/> if the <c>session</c>
        /// already contains <c>obj</c>.
        /// </returns>
        public object Generate(ISessionImplementor sessionImplementor, object obj)
        {
            ISession session = (ISession)sessionImplementor;

            object associatedObject = sessionImplementor.Factory
                .GetClassMetadata(obj.GetType())
                .GetPropertyValue(obj, propertyName, sessionImplementor.EntityMode);

            if (associatedObject == null)
            {
                throw new IdentifierGenerationException("attempted to assign id from null one-to-one property: " + propertyName);
            }

            EntityType type = (EntityType)sessionImplementor.Factory.GetClassMetadata(obj.GetType()).GetPropertyType(propertyName);

            object id;
            try
            {
                id = ForeignKeys.GetEntityIdentifierIfNotUnsaved(type.GetAssociatedEntityName(), associatedObject, sessionImplementor);
            }
            catch (TransientObjectException)
            {
                id = session.Save(associatedObject);
            }

            if (session.Contains(obj))
            {
                //abort the save (the object is already saved by a circular cascade)
                return IdentifierGeneratorFactory.ShortCircuitIndicator;
            }

            return id;
        }
        protected AbstractAuditWorkUnit(ISessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg,
									    Object id) {
		    this.sessionImplementor = sessionImplementor;
            this.verCfg = verCfg;
            this.EntityId = id;
            this.EntityName = entityName;
        }
		private object[] GetValues(object entity, EntityEntry entry, EntityMode entityMode, bool mightBeDirty, ISessionImplementor session)
		{
			object[] loadedState = entry.LoadedState;
			Status status = entry.Status;
			IEntityPersister persister = entry.Persister;

			object[] values;
			if (status == Status.Deleted)
			{
				//grab its state saved at deletion
				values = entry.DeletedState;
			}
			else if (!mightBeDirty && loadedState != null)
			{
				values = loadedState;
			}
			else
			{
				CheckId(entity, persister, entry.Id, entityMode);

				// grab its current state
				values = persister.GetPropertyValues(entity, entityMode);

				CheckNaturalId(persister, entry, values, loadedState, entityMode, session);
			}
			return values;
		}
Ejemplo n.º 19
0
 /// <summary>
 /// Creates a new PersistentSet initialized to the values in the Map.
 /// This constructor is NOT meant to be called from user code.
 /// </summary>
 /// <remarks>
 /// Only call this constructor if you consider the map initialized.
 /// </remarks>
 public PersistentSet(ISessionImplementor session, ISet collection)
     : base(session)
 {
     internalSet = collection;
     SetInitialized();
     IsDirectlyAccessible = true;
 }
Ejemplo n.º 20
0
        /// <summary>
        /// Create an action that will evict collection and entity regions based on queryspaces (table names).  
        /// </summary>
        public BulkOperationCleanupAction(ISessionImplementor session, ISet<string> querySpaces)
        {
            //from H3.2 TODO: cache the autodetected information and pass it in instead.
            this.session = session;

            ISet<string> tmpSpaces = new HashedSet<string>(querySpaces);
            ISessionFactoryImplementor factory = session.Factory;
            IDictionary acmd = factory.GetAllClassMetadata();
            foreach (DictionaryEntry entry in acmd)
            {
                string entityName = ((System.Type) entry.Key).FullName;
                IEntityPersister persister = factory.GetEntityPersister(entityName);
                string[] entitySpaces = persister.QuerySpaces;

                if (AffectedEntity(querySpaces, entitySpaces))
                {
                    if (persister.HasCache)
                    {
                        affectedEntityNames.Add(persister.EntityName);
                    }
                    ISet roles = session.Factory.GetCollectionRolesByEntityParticipant(persister.EntityName);
                    if (roles != null)
                    {
                        affectedCollectionRoles.AddAll(roles);
                    }
                    for (int y = 0; y < entitySpaces.Length; y++)
                    {
                        tmpSpaces.Add(entitySpaces[y]);
                    }
                }
            }
            spaces = new List<string>(tmpSpaces);
        }
Ejemplo n.º 21
0
 /// <summary>
 /// Construct an initialized PersistentMap based off the values from the existing IDictionary.
 /// </summary>
 /// <param name="session">The ISession the PersistentMap should be a part of.</param>
 /// <param name="map">The IDictionary that contains the initial values.</param>
 public PersistentMap(ISessionImplementor session, IDictionary map)
     : base(session)
 {
     this.map = map;
     SetInitialized();
     IsDirectlyAccessible = true;
 }
Ejemplo n.º 22
0
		public override object ReplaceElements(object original, object target, object owner, IDictionary copyCache, ISessionImplementor session)
		{
			ICollectionPersister cp = session.Factory.GetCollectionPersister(Role);

			IDictionary result = (IDictionary)target;
			result.Clear();

			IEnumerable iter = (IDictionary)original;
			foreach (DictionaryEntry me in iter)
			{
				object key = cp.IndexType.Replace(me.Key, null, session, owner, copyCache);
				object value = cp.ElementType.Replace(me.Value, null, session, owner, copyCache);
				result[key] = value;
			}

			var originalPc = original as IPersistentCollection;
			var resultPc = result as IPersistentCollection;
			if (originalPc != null && resultPc != null)
			{
				if (!originalPc.IsDirty)
					resultPc.ClearDirty();
			}

			return result;
		}
		public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session)
		{
			if (session.TransactionContext != null)
				return;
			if (System.Transactions.Transaction.Current == null)
				return;
			var transactionContext = new DistributedTransactionContext(session, System.Transactions.Transaction.Current);
			session.TransactionContext = transactionContext;
			logger.DebugFormat("enlisted into DTC transaction: {0}", transactionContext.AmbientTransation.IsolationLevel);
			session.AfterTransactionBegin(null);
			transactionContext.AmbientTransation.TransactionCompleted += delegate(object sender, TransactionEventArgs e)
			{
				bool wasSuccessful = false;
				try
				{
					wasSuccessful = e.Transaction.TransactionInformation.Status
					                == TransactionStatus.Committed;
				}
				catch (ObjectDisposedException ode)
				{
					logger.Warn("Completed transaction was disposed, assuming transaction rollback", ode);
				}
				session.AfterTransactionCompletion(wasSuccessful, null);
				if (transactionContext.ShouldCloseSessionOnDistributedTransactionCompleted)
				{
					session.CloseSessionFromDistributedTransaction();
				}
				session.TransactionContext = null;
			};
			transactionContext.AmbientTransation.EnlistVolatile(transactionContext, EnlistmentOptions.EnlistDuringPrepareRequired);
		}
Ejemplo n.º 24
0
		protected override object GetResultColumnOrRow(object[] row, IResultTransformer resultTransformer, IDataReader rs,
		                                               ISessionImplementor session)
		{
			object[] result;
			string[] aliases;

			if (translator.HasProjection)
			{
				IType[] types = translator.ProjectedTypes;
				result = new object[types.Length];
				string[] columnAliases = translator.ProjectedColumnAliases;

				for (int i = 0; i < result.Length; i++)
				{
					result[i] = types[i].NullSafeGet(rs, columnAliases[i], session, null);
				}
				aliases = translator.ProjectedAliases;
			}
			else
			{
				result = row;
				aliases = userAliases;
			}
			return translator.RootCriteria.ResultTransformer.TransformTuple(result, aliases);
		}
		/// <summary>
		/// Initializes a new instance of <see cref="ScheduledEntityAction"/>.
		/// </summary>
		/// <param name="session">The <see cref="ISessionImplementor"/> that the Action is occuring in.</param>
		/// <param name="id">The identifier of the object.</param>
		/// <param name="instance">The actual object instance.</param>
		/// <param name="persister">The <see cref="IClassPersister"/> that is responsible for the persisting the object.</param>
		protected ScheduledEntityAction( ISessionImplementor session, object id, object instance, IClassPersister persister )
		{
			this.session = session;
			this.id = id;
			this.persister = persister;
			this.instance = instance;
		}
Ejemplo n.º 26
0
		/// <summary> 
		/// Bind named parameters to the <tt>PreparedStatement</tt>. This has an
		/// empty implementation on this superclass and should be implemented by
		/// subclasses (queries) which allow named parameters.
		/// </summary>
		private void BindNamedParameters(IDbCommand ps, IDictionary namedParams, int start, ISessionImplementor session)
		{
			if (namedParams != null)
			{
				// assumes that types are all of span 1
				int result = 0;
				foreach (DictionaryEntry param in namedParams)
				{
					string name = (string)param.Key;
					TypedValue typedval = (TypedValue)param.Value;

					int[] locs = GetNamedParameterLocs(name);
					for (int i = 0; i < locs.Length; i++)
					{
						if (log.IsDebugEnabled)
						{
							log.Debug(string.Format("BindNamedParameters() {0} -> {1} [{2}]", typedval.Value, name, (locs[i] + start)));
						}
						typedval.Type.NullSafeSet(ps, typedval.Value, locs[i] + start, session);
					}
					result += locs.Length;
				}
				return;
			}
			else
			{
				return;
			}
		}
		private bool FlushMightBeNeeded(ISessionImplementor source)
		{
			return
				!(source.FlushMode < FlushMode.Auto)
				&& source.DontFlushFromFind == 0
				&& ((source.PersistenceContext.EntityEntries.Count > 0) || (source.PersistenceContext.CollectionEntries.Count > 0));
		}
Ejemplo n.º 28
0
        /// <summary> 
        /// Initialize the role of the collection. 
        /// </summary>
        /// <param name="collection">The collection to be updated by reachibility. </param>
        /// <param name="type">The type of the collection. </param>
        /// <param name="entity">The owner of the collection. </param>
        /// <param name="session">The session.</param>
        public static void ProcessReachableCollection(IPersistentCollection collection, CollectionType type, object entity, ISessionImplementor session)
        {
            collection.Owner = entity;
            CollectionEntry ce = session.PersistenceContext.GetCollectionEntry(collection);

            if (ce == null)
            {
                // refer to comment in StatefulPersistenceContext.addCollection()
                throw new HibernateException(string.Format("Found two representations of same collection: {0}", type.Role));
            }

            // The CollectionEntry.isReached() stuff is just to detect any silly users
            // who set up circular or shared references between/to collections.
            if (ce.IsReached)
            {
                // We've been here before
                throw new HibernateException(string.Format("Found shared references to a collection: {0}", type.Role));
            }
            ce.IsReached = true;

            ISessionFactoryImplementor factory = session.Factory;
            ICollectionPersister persister = factory.GetCollectionPersister(type.Role);
            ce.CurrentPersister = persister;
            ce.CurrentKey = type.GetKeyOfOwner(entity, session); //TODO: better to pass the id in as an argument?

            if (log.IsDebugEnabled)
            {
                log.Debug("Collection found: " +
                    MessageHelper.InfoString(persister, ce.CurrentKey, factory) + ", was: " +
                    MessageHelper.InfoString(ce.LoadedPersister, ce.LoadedKey, factory) +
                    (collection.WasInitialized ? " (initialized)" : " (uninitialized)"));
            }

            PrepareCollectionForUpdate(collection, ce);
        }
		/// <summary>
		/// Initializes a new instance of <see cref="ScheduledCollectionUpdate"/>.
		/// </summary>
		/// <param name="collection">The <see cref="IPersistentCollection"/> to update.</param>
		/// <param name="persister">The <see cref="ICollectionPersister"/> that is responsible for the persisting the Collection.</param>
		/// <param name="id">The identifier of the Collection owner.</param>
		/// <param name="emptySnapshot">Indicates if the Collection was empty when it was loaded.</param>
		/// <param name="session">The <see cref="ISessionImplementor"/> that the Action is occuring in.</param>
		public ScheduledCollectionUpdate(IPersistentCollection collection, ICollectionPersister persister, object id,
		                                 bool emptySnapshot, ISessionImplementor session)
			: base(persister, id, session)
		{
			_collection = collection;
			_emptySnapshot = emptySnapshot;
		}
Ejemplo n.º 30
0
    public INHibernateProxy GetProxy(object id, ISessionImplementor session)
    {
        INHibernateProxy proxy;
        try
        {
            object generatedProxy;
            LazyInitializer initializer = new LazyInitializer(_entityName, _persistentClass, id, _getIdentifierMethod, _setIdentifierMethod, _componentIdType, session);
            IInterceptor[] interceptors = new IInterceptor[] { initializer };

            object[] args;
            if (_isClassProxy)
            {
                args = new object[] { interceptors };
            }
            else
            {
                args = new object[] { interceptors, new object() };
            }
            generatedProxy = Activator.CreateInstance(_proxyType, args);

            initializer._constructed = true;
            proxy = (INHibernateProxy)generatedProxy;
        }
        catch (Exception e)
        {
            string message = "Creating a proxy instance failed";
            _log.Error(message, e);
            throw new HibernateException(message, e);
        }

        return proxy;
    }
Ejemplo n.º 31
0
		public INHibernateProxy GetProxy(object id, ISessionImplementor session)
		{
			return new MapProxy(new MapLazyInitializer(entityName, id, session));
		}
Ejemplo n.º 32
0
        /// <summary>
        /// Perform the second step of 2-phase load. Fully initialize the entity instance.
        /// After processing a JDBC result set, we "resolve" all the associations
        /// between the entities which were instantiated and had their state
        /// "hydrated" into an array
        /// </summary>
        internal static async Task InitializeEntityAsync(object entity, bool readOnly, ISessionImplementor session, PreLoadEvent preLoadEvent, PostLoadEvent postLoadEvent,
                                                         Action <IEntityPersister, CachePutData> cacheBatchingHandler, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            //TODO: Should this be an InitializeEntityEventListener??? (watch out for performance!)

            Stopwatch stopWatch = null;

            if (session.Factory.Statistics.IsStatisticsEnabled)
            {
                stopWatch = Stopwatch.StartNew();
            }

            IPersistenceContext persistenceContext = session.PersistenceContext;
            EntityEntry         entityEntry        = persistenceContext.GetEntry(entity);

            if (entityEntry == null)
            {
                throw new AssertionFailure("possible non-threadsafe access to the session");
            }
            IEntityPersister persister = entityEntry.Persister;
            object           id        = entityEntry.Id;

            object[] hydratedState = entityEntry.LoadedState;

            if (log.IsDebugEnabled())
            {
                log.Debug("resolving associations for {0}", MessageHelper.InfoString(persister, id, session.Factory));
            }

            IType[] types = persister.PropertyTypes;
            var     collectionToResolveIndexes = new List <int>(hydratedState.Length);

            for (int i = 0; i < hydratedState.Length; i++)
            {
                object value = hydratedState[i];
                if (!Equals(LazyPropertyInitializer.UnfetchedProperty, value) && !(Equals(BackrefPropertyAccessor.Unknown, value)))
                {
                    if (types[i].IsCollectionType)
                    {
                        // Resolve them last, because they may depend on other properties if they use a property-ref
                        collectionToResolveIndexes.Add(i);
                        continue;
                    }

                    hydratedState[i] = await(types[i].ResolveIdentifierAsync(value, session, entity, cancellationToken)).ConfigureAwait(false);
                }
            }

            foreach (var i in collectionToResolveIndexes)
            {
                hydratedState[i] = await(types[i].ResolveIdentifierAsync(hydratedState[i], session, entity, cancellationToken)).ConfigureAwait(false);
            }

            //Must occur after resolving identifiers!
            if (session.IsEventSource)
            {
                preLoadEvent.Entity    = entity;
                preLoadEvent.State     = hydratedState;
                preLoadEvent.Id        = id;
                preLoadEvent.Persister = persister;
                IPreLoadEventListener[] listeners = session.Listeners.PreLoadEventListeners;
                for (int i = 0; i < listeners.Length; i++)
                {
                    await(listeners[i].OnPreLoadAsync(preLoadEvent, cancellationToken)).ConfigureAwait(false);
                }
            }

            persister.SetPropertyValues(entity, hydratedState);

            ISessionFactoryImplementor factory = session.Factory;

            if (persister.HasCache && session.CacheMode.HasFlag(CacheMode.Put))
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("adding entity to second-level cache: {0}", MessageHelper.InfoString(persister, id, session.Factory));
                }

                object     version = Versioning.GetVersion(hydratedState, persister);
                CacheEntry entry   =
                    await(CacheEntry.CreateAsync(hydratedState, persister, version, session, entity, cancellationToken)).ConfigureAwait(false);
                CacheKey cacheKey = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);

                if (cacheBatchingHandler != null && persister.IsBatchLoadable)
                {
                    cacheBatchingHandler(
                        persister,
                        new CachePutData(
                            cacheKey,
                            persister.CacheEntryStructure.Structure(entry),
                            version,
                            persister.IsVersioned ? persister.VersionType.Comparator : null,
                            UseMinimalPuts(session, entityEntry)));
                }
                else
                {
                    bool put =
                        await(persister.Cache.PutAsync(cacheKey, persister.CacheEntryStructure.Structure(entry), session.Timestamp, version,
                                                       persister.IsVersioned ? persister.VersionType.Comparator : null,
                                                       UseMinimalPuts(session, entityEntry), cancellationToken)).ConfigureAwait(false);

                    if (put && factory.Statistics.IsStatisticsEnabled)
                    {
                        factory.StatisticsImplementor.SecondLevelCachePut(persister.Cache.RegionName);
                    }
                }
            }

            bool isReallyReadOnly = readOnly;

            if (!persister.IsMutable)
            {
                isReallyReadOnly = true;
            }
            else
            {
                object proxy = persistenceContext.GetProxy(entityEntry.EntityKey);
                if (proxy != null)
                {
                    // there is already a proxy for this impl
                    // only set the status to read-only if the proxy is read-only
                    isReallyReadOnly = ((INHibernateProxy)proxy).HibernateLazyInitializer.ReadOnly;
                }
            }

            if (isReallyReadOnly)
            {
                //no need to take a snapshot - this is a
                //performance optimization, but not really
                //important, except for entities with huge
                //mutable property values
                persistenceContext.SetEntryStatus(entityEntry, Status.ReadOnly);
            }
            else
            {
                //take a snapshot
                TypeHelper.DeepCopy(hydratedState, persister.PropertyTypes, persister.PropertyUpdateability, hydratedState, session);
                persistenceContext.SetEntryStatus(entityEntry, Status.Loaded);
            }

            persister.AfterInitialize(entity, session);

            if (session.IsEventSource)
            {
                postLoadEvent.Entity    = entity;
                postLoadEvent.Id        = id;
                postLoadEvent.Persister = persister;
                IPostLoadEventListener[] listeners = session.Listeners.PostLoadEventListeners;
                for (int i = 0; i < listeners.Length; i++)
                {
                    listeners[i].OnPostLoad(postLoadEvent);
                }
            }

            if (log.IsDebugEnabled())
            {
                log.Debug("done materializing entity {0}", MessageHelper.InfoString(persister, id, session.Factory));
            }

            if (stopWatch != null)
            {
                stopWatch.Stop();
                factory.StatisticsImplementor.LoadEntity(persister.EntityName, stopWatch.Elapsed);
            }
        }
Ejemplo n.º 33
0
 public IPersistentCollection Wrap(ISessionImplementor session, object collection)
 {
     return(new PersistentMySet <T>(session, (IMySet <T>)collection));
 }
Ejemplo n.º 34
0
        public object ReplaceElements(object original, object target, NHibernate.Persister.Collection.ICollectionPersister persister, object owner, IDictionary copyCache, ISessionImplementor session)
        {
            var result = (MySet <T>)target;

            result.Clear();
            foreach (var item in (IEnumerable <T>)original)
            {
                result.Add(item);
            }
            return(result);
        }
Ejemplo n.º 35
0
 public IPersistentCollection Instantiate(ISessionImplementor session, NHibernate.Persister.Collection.ICollectionPersister persister)
 {
     return(new PersistentMySet <T>(session));
 }
Ejemplo n.º 36
0
        public override async Task <object> DoWorkInCurrentTransactionAsync(ISessionImplementor session, DbConnection conn, DbTransaction transaction, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            long result;
            int  updatedRows;

            do
            {
                try
                {
                    object selectedValue;

                    var selectCmd = session.Factory.ConnectionProvider.Driver.GenerateCommand(CommandType.Text, _selectQuery, SqlTypeFactory.NoTypes);
                    using (selectCmd)
                    {
                        selectCmd.Connection  = conn;
                        selectCmd.Transaction = transaction;
                        PersistentIdGeneratorParmsNames.SqlStatementLogger.LogCommand(selectCmd, FormatStyle.Basic);

                        selectedValue = await(selectCmd.ExecuteScalarAsync(cancellationToken)).ConfigureAwait(false);
                    }

                    if (selectedValue == null)
                    {
                        Log.Error("could not read a hi value - you need to populate the table: {0}", _tableName);
                        throw new IdentifierGenerationException("could not read a hi value - you need to populate the table: " + _tableName);
                    }
                    result = Convert.ToInt64(selectedValue);
                }
                catch (OperationCanceledException) { throw; }
                catch (Exception sqle)
                {
                    Log.Error(sqle, "could not read a hi value");
                    throw;
                }

                try
                {
                    var updateCmd = session.Factory.ConnectionProvider.Driver.GenerateCommand(CommandType.Text, _updateQuery, _updateParameterTypes);
                    using (updateCmd)
                    {
                        updateCmd.Connection  = conn;
                        updateCmd.Transaction = transaction;
                        PersistentIdGeneratorParmsNames.SqlStatementLogger.LogCommand(updateCmd, FormatStyle.Basic);

                        int increment = _applyIncrementSizeToSourceValues ? _incrementSize : 1;
                        updateCmd.Parameters[0].Value = result + increment;
                        updateCmd.Parameters[1].Value = result;
                        updatedRows = await(updateCmd.ExecuteNonQueryAsync(cancellationToken)).ConfigureAwait(false);
                    }
                }
                catch (OperationCanceledException) { throw; }
                catch (Exception sqle)
                {
                    Log.Error(sqle, "could not update hi value in: {0}", _tableName);
                    throw;
                }
            }while (updatedRows == 0);

            _accessCounter++;

            return(result);
        }
Ejemplo n.º 37
0
        public override async Task <object> DoWorkInCurrentTransactionAsync(ISessionImplementor session, DbConnection conn,
                                                                            DbTransaction transaction, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            long result;
            int  rows;

            do
            {
                //the loop ensure atomicitiy of the
                //select + uspdate even for no transaction
                //or read committed isolation level (needed for .net?)

                var          qps = conn.CreateCommand();
                DbDataReader rs  = null;
                qps.CommandText = query;
                qps.CommandType = CommandType.Text;
                qps.Transaction = transaction;
                PersistentIdGeneratorParmsNames.SqlStatementLogger.LogCommand("Reading high value:", qps, FormatStyle.Basic);
                try
                {
                    rs = await(qps.ExecuteReaderAsync(cancellationToken)).ConfigureAwait(false);
                    if (!await(rs.ReadAsync(cancellationToken)).ConfigureAwait(false))
                    {
                        string err;
                        if (string.IsNullOrEmpty(whereClause))
                        {
                            err = "could not read a hi value - you need to populate the table: " + tableName;
                        }
                        else
                        {
                            err = string.Format("could not read a hi value from table '{0}' using the where clause ({1})- you need to populate the table.", tableName, whereClause);
                        }
                        log.Error(err);
                        throw new IdentifierGenerationException(err);
                    }
                    result = Convert.ToInt64(columnType.Get(rs, 0, session));
                }
                catch (Exception e)
                {
                    log.Error("could not read a hi value", e);
                    throw;
                }
                finally
                {
                    if (rs != null)
                    {
                        rs.Close();
                    }
                    qps.Dispose();
                }

                var ups = session.Factory.ConnectionProvider.Driver.GenerateCommand(CommandType.Text, updateSql, parameterTypes);
                ups.Connection  = conn;
                ups.Transaction = transaction;

                try
                {
                    columnType.Set(ups, result + 1, 0, session);
                    columnType.Set(ups, result, 1, session);

                    PersistentIdGeneratorParmsNames.SqlStatementLogger.LogCommand("Updating high value:", ups, FormatStyle.Basic);

                    rows = await(ups.ExecuteNonQueryAsync(cancellationToken)).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    log.Error("could not update hi value in: " + tableName, e);
                    throw;
                }
                finally
                {
                    ups.Dispose();
                }
            }while (rows == 0);

            return(result);
        }
Ejemplo n.º 38
0
 /// <summary>
 /// When implemented by a class, gets the object in the
 /// <see cref="DbDataReader"/> for the Property.
 /// </summary>
 /// <param name="rs">The <see cref="DbDataReader"/> that contains the value.</param>
 /// <param name="name">The name of the field to get the value from.</param>
 /// <param name="session">The session for which the operation is done.</param>
 /// <returns>An object with the value from the database.</returns>
 /// <remarks>
 /// Most implementors just call the <see cref="Get(DbDataReader, int, ISessionImplementor)"/>
 /// overload of this method.
 /// </remarks>
 public abstract object Get(DbDataReader rs, string name, ISessionImplementor session);
Ejemplo n.º 39
0
 /// <summary>
 /// When implemented by a class, put the value from the mapped
 /// Property into to the <see cref="DbCommand"/>.
 /// </summary>
 /// <param name="cmd">The <see cref="DbCommand"/> to put the value into.</param>
 /// <param name="value">The object that contains the value.</param>
 /// <param name="index">The index of the <see cref="DbParameter"/> to start writing the values to.</param>
 /// <param name="session">The session for which the operation is done.</param>
 /// <remarks>
 /// Implementors do not need to handle possibility of null values because this will
 /// only be called from <see cref="NullSafeSet(DbCommand, object, int, ISessionImplementor)"/> after
 /// it has checked for nulls.
 /// </remarks>
 public abstract void Set(DbCommand cmd, object value, int index, ISessionImplementor session);
Ejemplo n.º 40
0
 public void SetSession(ISessionImplementor s)
 {
 }
Ejemplo n.º 41
0
 /// <inheritdoc />
 /// <remarks>
 /// <para>
 /// This implementation forwards the call to <see cref="NullSafeGet(DbDataReader, String, ISessionImplementor)" />.
 /// </para>
 /// <para>
 /// It has been "sealed" because the Types inheriting from <see cref="NullableType"/>
 /// do not need to and should not override this method.  All of their implementation
 /// should be in <see cref="NullSafeGet(DbDataReader, String, ISessionImplementor)" />.
 /// </para>
 /// </remarks>
 public sealed override object NullSafeGet(DbDataReader rs, string name, ISessionImplementor session, object owner)
 {
     return(NullSafeGet(rs, name, session));
 }
Ejemplo n.º 42
0
 /// <summary>
 /// When implemented by a class, gets the object in the
 /// <see cref="DbDataReader"/> for the Property.
 /// </summary>
 /// <param name="rs">The <see cref="DbDataReader"/> that contains the value.</param>
 /// <param name="index">The index of the field to get the value from.</param>
 /// <param name="session">The session for which the operation is done.</param>
 /// <returns>An object with the value from the database.</returns>
 public abstract object Get(DbDataReader rs, int index, ISessionImplementor session);
Ejemplo n.º 43
0
        /// <inheritdoc />
        /// <remarks>
        /// <para>
        /// This method has been "sealed" because the Types inheriting from <see cref="NullableType"/>
        /// do not need to and should not override this method.
        /// </para>
        /// <para>
        /// This method checks to see if value is null, if it is then the value of
        /// <see cref="DBNull"/> is written to the <see cref="DbCommand"/>.
        /// </para>
        /// <para>
        /// If the value is not null, then the method <see cref="Set(DbCommand, object, int, ISessionImplementor)"/>
        /// is called and that method is responsible for setting the value.
        /// </para>
        /// </remarks>
        public sealed override void NullSafeSet(DbCommand st, object value, int index, ISessionImplementor session)
        {
            if (value == null)
            {
                if (IsDebugEnabled)
                {
                    Log.Debug("binding null to parameter: {0}", index);
                }

                //Do we check IsNullable?
                // TODO: find out why a certain Parameter would not take a null value...
                // From reading the .NET SDK the default is to NOT accept a null value.
                // I definitely need to look into this more...
                st.Parameters[index].Value = DBNull.Value;
            }
            else
            {
                if (IsDebugEnabled)
                {
                    Log.Debug("binding '{0}' to parameter: {1}", ToString(value), index);
                }

                Set(st, value, index, session);
            }
        }
Ejemplo n.º 44
0
 public override bool IsDirty(object old, object current, bool[] checkable, ISessionImplementor session)
 {
     return(checkable[0] && IsDirty(old, current, session));
 }
Ejemplo n.º 45
0
 public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session)
 {
     return(Get(owner));
 }
Ejemplo n.º 46
0
 /// <summary>
 /// Extracts the values of the fields from the DataReader
 /// </summary>
 /// <param name="rs">The DataReader positioned on the correct record</param>
 /// <param name="names">An array of field names.</param>
 /// <param name="session">The session for which the operation is done.</param>
 /// <returns>The value off the field from the DataReader</returns>
 /// <remarks>
 /// In this class this just ends up passing the first name to the NullSafeGet method
 /// that takes a string, not a string[].
 ///
 /// I don't know why this method is in here - it doesn't look like anybody that inherits
 /// from NullableType overrides this...
 ///
 /// TODO: determine if this is needed
 /// </remarks>
 public virtual object NullSafeGet(DbDataReader rs, string[] names, ISessionImplementor session)
 {
     return(NullSafeGet(rs, names[0], session));
 }
Ejemplo n.º 47
0
 public override object Get(object value, ISessionImplementor session, object owner)
 {
     return(((T[])value).ToList());
 }
Ejemplo n.º 48
0
 public override void NullSafeSet(DbCommand st, object value, int index, bool[] settable, ISessionImplementor session)
 {
     if (settable[0])
     {
         NullSafeSet(st, value, index, session);
     }
 }
Ejemplo n.º 49
0
        /// <summary>
        /// Load an instance by a unique key that is not the primary key.
        /// </summary>
        /// <param name="entityName">The name of the entity to load </param>
        /// <param name="uniqueKeyPropertyName">The name of the property defining the unique key. </param>
        /// <param name="key">The unique key property value. </param>
        /// <param name="session">The originating session. </param>
        /// <returns> The loaded entity </returns>
        public object LoadByUniqueKey(string entityName, string uniqueKeyPropertyName, object key, ISessionImplementor session)
        {
            ISessionFactoryImplementor factory   = session.Factory;
            IUniqueKeyLoadable         persister = (IUniqueKeyLoadable)factory.GetEntityPersister(entityName);

            //TODO: implement caching?! proxies?!

            var keyType = GetIdentifierOrUniqueKeyType(factory)
                          // EntityUniqueKey was doing this on the type. I suspect this was needed only for its usage in Loader,
                          // which can work with entities as keys not yet instanciated and just represented by their identifiers.
                          // But since removing this call from EntityUniqueKey is done for a patch and that the code path here has
                          // no known bugs with this GetSemiResolvedType, moving its call here for avoiding altering this code
                          // path. See GH1645.
                          .GetSemiResolvedType(factory);
            EntityUniqueKey euk =
                new EntityUniqueKey(
                    entityName,
                    uniqueKeyPropertyName,
                    key,
                    keyType,
                    session.Factory);

            IPersistenceContext persistenceContext = session.PersistenceContext;

            try
            {
                object result = persistenceContext.GetEntity(euk);
                if (result == null)
                {
                    result = persister.LoadByUniqueKey(uniqueKeyPropertyName, key, session);
                }
                return(result == null ? null : persistenceContext.ProxyFor(result));
            }
            catch (HibernateException)
            {
                // Do not call Convert on HibernateExceptions
                throw;
            }
            catch (Exception sqle)
            {
                throw ADOExceptionHelper.Convert(factory.SQLExceptionConverter, sqle, "Error performing LoadByUniqueKey");
            }
        }
Ejemplo n.º 50
0
 public override void Set(DbParameter parameter, object value, ISessionImplementor session)
 {
     parameter.Value = value;
 }
Ejemplo n.º 51
0
 public abstract override object Hydrate(DbDataReader rs, string[] names, ISessionImplementor session, object owner);
Ejemplo n.º 52
0
 public virtual bool IsNull(object owner, ISessionImplementor session)
 {
     return(false);
 }
Ejemplo n.º 53
0
 protected internal object GetIdentifier(object value, ISessionImplementor session)
 {
     return(ForeignKeys.GetEntityIdentifierIfNotUnsaved(GetAssociatedEntityName(), value, session));            //tolerates nulls
 }
Ejemplo n.º 54
0
 /// <summary> Convenience method to locate the identifier type of the associated entity. </summary>
 /// <param name="session">The originating session </param>
 /// <returns> The identifier type </returns>
 internal virtual IType GetIdentifierType(ISessionImplementor session)
 {
     return(GetIdentifierType(session.Factory));
 }
Ejemplo n.º 55
0
		public bool Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, bool isNaturalKeyLookup, ISessionImplementor session)
		{
			if (isNaturalKeyLookup && result.Count == 0)
				return false;

			var ts = session.Factory.Settings.CacheProvider.NextTimestamp();

			Log.Debug("caching query results in region: '{0}'; {1}", _regionName, key);

			Cache.Put(key, GetCacheableResult(returnTypes, session, result, ts));

			return true;
		}
Ejemplo n.º 56
0
 /// <summary>
 /// Converts the id contained in the <see cref="DbDataReader"/> to an object.
 /// </summary>
 /// <param name="rs">The <see cref="DbDataReader"/> that contains the query results.</param>
 /// <param name="names">A string array of column names that contain the id.</param>
 /// <param name="session">The <see cref="ISessionImplementor"/> this is occurring in.</param>
 /// <param name="owner">The object that this Entity will be a part of.</param>
 /// <returns>
 /// An instance of the object or <see langword="null" /> if the identifer was null.
 /// </returns>
 public override sealed object NullSafeGet(DbDataReader rs, string[] names, ISessionImplementor session, object owner)
 {
     return(ResolveIdentifier(Hydrate(rs, names, session, owner), session, owner));
 }
Ejemplo n.º 57
0
		public IList Get(QueryKey key, ICacheAssembler[] returnTypes, bool isNaturalKeyLookup, ISet<string> spaces, ISessionImplementor session)
		{
			if (Log.IsDebugEnabled())
				Log.Debug("checking cached query results in region: '{0}'; {1}", _regionName, key);

			var cacheable = (IList) Cache.Get(key);
			if (cacheable == null)
			{
				Log.Debug("query results were not found in cache: {0}", key);
				return null;
			}

			var timestamp = (long) cacheable[0];

			if (Log.IsDebugEnabled())
				Log.Debug("Checking query spaces for up-to-dateness [{0}]", StringHelper.CollectionToString(spaces));

			if (!isNaturalKeyLookup && !IsUpToDate(spaces, timestamp))
			{
				Log.Debug("cached query results were not up to date for: {0}", key);
				return null;
			}

			return GetResultFromCacheable(key, returnTypes, isNaturalKeyLookup, session, cacheable);
		}
Ejemplo n.º 58
0
 public override object NullSafeGet(DbDataReader rs, string name, ISessionImplementor session, object owner)
 {
     return(NullSafeGet(rs, new string[] { name }, session, owner));
 }
Ejemplo n.º 59
0
		public override object DoWorkInCurrentTransaction(ISessionImplementor session, DbConnection conn, DbTransaction transaction)
		{
			long result;
			int updatedRows;

			do
			{
				object selectedValue;

				try
				{
					var selectCmd = session.Factory.ConnectionProvider.Driver.GenerateCommand(CommandType.Text, selectQuery, selectParameterTypes);
					using (selectCmd)
					{
						selectCmd.Connection = conn;
						selectCmd.Transaction = transaction;
						string s = selectCmd.CommandText;
						selectCmd.Parameters[0].Value = SegmentValue;
						PersistentIdGeneratorParmsNames.SqlStatementLogger.LogCommand(selectCmd, FormatStyle.Basic);

						selectedValue = selectCmd.ExecuteScalar();
					}

					if (selectedValue == null)
					{
						result = InitialValue;

						var insertCmd = session.Factory.ConnectionProvider.Driver.GenerateCommand(CommandType.Text, insertQuery, insertParameterTypes);
						using (insertCmd)
						{
							insertCmd.Connection = conn;
							insertCmd.Transaction = transaction;

							insertCmd.Parameters[0].Value = SegmentValue;
							insertCmd.Parameters[1].Value = result;

							PersistentIdGeneratorParmsNames.SqlStatementLogger.LogCommand(insertCmd, FormatStyle.Basic);
							insertCmd.ExecuteNonQuery();
						}
					}
					else
					{
						result = Convert.ToInt64(selectedValue);
					}
				}
				catch (Exception ex)
				{
					log.Error("Unable to read or initialize hi value in " + TableName, ex);
					throw;
				}


				try
				{
					var updateCmd = session.Factory.ConnectionProvider.Driver.GenerateCommand(CommandType.Text, updateQuery, updateParameterTypes);
					using (updateCmd)
					{
						updateCmd.Connection = conn;
						updateCmd.Transaction = transaction;

						int increment = Optimizer.ApplyIncrementSizeToSourceValues ? IncrementSize : 1;
						updateCmd.Parameters[0].Value = result + increment;
						updateCmd.Parameters[1].Value = result;
						updateCmd.Parameters[2].Value = SegmentValue;
						PersistentIdGeneratorParmsNames.SqlStatementLogger.LogCommand(updateCmd, FormatStyle.Basic);
						updatedRows = updateCmd.ExecuteNonQuery();
					}
				}
				catch (Exception ex)
				{
					log.Error("Unable to update hi value in " + TableName, ex);
					throw;
				}
			}
			while (updatedRows == 0);

			TableAccessCount++;

			return result;
		}
Ejemplo n.º 60
0
		/// <inheritdoc />
		public IList[] GetMany(
			QueryKey[] keys,
			QueryParameters[] queryParameters,
			ICacheAssembler[][] returnTypes,
			ISet<string>[] spaces,
			ISessionImplementor session)
		{
			if (Log.IsDebugEnabled())
				Log.Debug("checking cached query results in region: '{0}'; {1}", _regionName, StringHelper.CollectionToString(keys));

			var cacheables = _cache.GetMany(keys);

			var spacesToCheck = new List<ISet<string>>();
			var checkedSpacesIndexes = new HashSet<int>();
			var checkedSpacesTimestamp = new List<long>();
			for (var i = 0; i < keys.Length; i++)
			{
				var cacheable = (IList) cacheables[i];
				if (cacheable == null)
				{
					Log.Debug("query results were not found in cache: {0}", keys[i]);
					continue;
				}

				var querySpaces = spaces[i];
				if (queryParameters[i].NaturalKeyLookup || querySpaces.Count == 0)
					continue;

				spacesToCheck.Add(querySpaces);
				checkedSpacesIndexes.Add(i);
				// The timestamp is the first element of the cache result.
				checkedSpacesTimestamp.Add((long) cacheable[0]);
				if (Log.IsDebugEnabled())
					Log.Debug("Checking query spaces for up-to-dateness [{0}]", StringHelper.CollectionToString(querySpaces));
			}

			var upToDates = spacesToCheck.Count > 0
				? _updateTimestampsCache.AreUpToDate(spacesToCheck.ToArray(), checkedSpacesTimestamp.ToArray())
				: Array.Empty<bool>();

			var upToDatesIndex = 0;
			var persistenceContext = session.PersistenceContext;
			var defaultReadOnlyOrig = persistenceContext.DefaultReadOnly;
			var results = new IList[keys.Length];
			var finalReturnTypes = new ICacheAssembler[keys.Length][];
			try
			{
				session.PersistenceContext.BatchFetchQueue.InitializeQueryCacheQueue();

				for (var i = 0; i < keys.Length; i++)
				{
					var cacheable = (IList) cacheables[i];
					if (cacheable == null)
						continue;

					var key = keys[i];
					if (checkedSpacesIndexes.Contains(i) && !upToDates[upToDatesIndex++])
					{
						Log.Debug("cached query results were not up to date for: {0}", key);
						continue;
					}

					var queryParams = queryParameters[i];
					if (queryParams.IsReadOnlyInitialized)
						persistenceContext.DefaultReadOnly = queryParams.ReadOnly;
					else
						queryParams.ReadOnly = persistenceContext.DefaultReadOnly;

					Log.Debug("returning cached query results for: {0}", key);

					finalReturnTypes[i] = GetReturnTypes(key, returnTypes[i], cacheable);
					PerformBeforeAssemble(finalReturnTypes[i], session, cacheable);
				}

				for (var i = 0; i < keys.Length; i++)
				{
					if (finalReturnTypes[i] == null)
					{
						continue;
					}

					var queryParams = queryParameters[i];
					// Adjust the session cache mode, as PerformAssemble assemble types which may cause
					// entity loads, which may interact with the cache.
					using (session.SwitchCacheMode(queryParams.CacheMode))
					{
						try
						{
							results[i] = PerformAssemble(keys[i], finalReturnTypes[i], queryParams.NaturalKeyLookup, session, (IList) cacheables[i]);
						}
						finally
						{
							persistenceContext.DefaultReadOnly = defaultReadOnlyOrig;
						}
					}
				}

				for (var i = 0; i < keys.Length; i++)
				{
					if (finalReturnTypes[i] == null)
					{
						continue;
					}

					var queryParams = queryParameters[i];
					// Adjust the session cache mode, as InitializeCollections will initialize collections,
					// which may interact with the cache.
					using (session.SwitchCacheMode(queryParams.CacheMode))
					{
						try
						{
							InitializeCollections(finalReturnTypes[i], session, results[i], (IList) cacheables[i]);
						}
						finally
						{
							persistenceContext.DefaultReadOnly = defaultReadOnlyOrig;
						}
					}
				}
			}
			finally
			{
				session.PersistenceContext.BatchFetchQueue.TerminateQueryCacheQueue();
			}

			return results;
		}