/// <summary></summary> public override void Execute() { CacheKey ck = null; if (Persister.HasCache) { ck = new CacheKey( Id, Persister.IdentifierType, (string) Persister.IdentifierSpace, Session.Factory ); _lock = Persister.Cache.Lock(ck, lastVersion); } Persister.Update(Id, state, dirtyFields, hasDirtyCollection, previousState, lastVersion, Instance, Session); EntityEntry entry = Session.GetEntry(Instance); if (entry == null) { throw new AssertionFailure("possible nonthreadsafe access to session"); } if (entry.Status == Status.Loaded || Persister.IsVersionPropertyGenerated) { // get the updated snapshot of the entity state by cloning current state; // it is safe to copy in place, since by this time no-one else (should have) // has a reference to the array TypeFactory.DeepCopy( state, Persister.PropertyTypes, Persister.PropertyCheckability, state); if (Persister.HasUpdateGeneratedProperties) { // this entity defines proeprty generation, so process those generated // values... Persister.ProcessUpdateGeneratedProperties(Id, Instance, state, Session); if (Persister.IsVersionPropertyGenerated) { nextVersion = Versioning.GetVersion(state, Persister); } } // have the entity entry perform post-update processing, passing it the // update state and the new version (if one). entry.PostUpdate(Instance, state, nextVersion); } if (Persister.HasCache) { if (Persister.IsCacheInvalidationRequired || entry.Status != Status.Loaded) { Persister.Cache.Evict(ck); } else { // TODO: Inefficient if that cache is just going to ignore the updated state! cacheEntry = new CacheEntry(Instance, Persister, Session); Persister.Cache.Update(ck, cacheEntry); } } }
public override void AfterTransactionCompletion(bool success) { IEntityPersister persister = Persister; if (persister.HasCache) { CacheKey ck = new CacheKey(Id, persister.IdentifierType, persister.RootEntityName, Session.EntityMode, Session.Factory); if (success && cacheEntry != null) { bool put = persister.Cache.AfterUpdate(ck, cacheEntry, nextVersion, slock); if (put && Session.Factory.Statistics.IsStatisticsEnabled) { Session.Factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName); } } else { persister.Cache.Release(ck, slock); } } if (success) { PostCommitUpdate(); } }
public bool Put(CacheKey key, object value, long timestamp, object version, IComparer versionComparator, bool minimalPut) { if (timestamp == long.MinValue) { // MinValue means cache is disabled return false; } lock (lockObject) { if (minimalPut && cache.Get(key) != null) { if (log.IsDebugEnabled) { log.Debug("item already cached: " + key); } return false; } if (log.IsDebugEnabled) { log.Debug("Caching: " + key); } cache.Put(key, value); return true; } }
/// <summary> Try to initialize a collection from the cache</summary> private bool InitializeCollectionFromCache(object id, ICollectionPersister persister, IPersistentCollection collection, ISessionImplementor source) { if (!(source.EnabledFilters.Count == 0) && persister.IsAffectedByEnabledFilters(source)) { log.Debug("disregarding cached version (if any) of collection due to enabled filters "); return false; } bool useCache = persister.HasCache && ((source.CacheMode & CacheMode.Get) == CacheMode.Get); if (!useCache) { return false; } else { ISessionFactoryImplementor factory = source.Factory; CacheKey ck = new CacheKey(id, persister.KeyType, persister.Role, source.EntityMode, factory); object ce = persister.Cache.Get(ck, source.Timestamp); if (factory.Statistics.IsStatisticsEnabled) { if (ce == null) { factory.StatisticsImplementor.SecondLevelCacheMiss(persister.Cache.RegionName); } else { factory.StatisticsImplementor.SecondLevelCacheHit(persister.Cache.RegionName); } } if (ce == null) { log.DebugFormat("Collection cache miss: {0}", ck); } else { log.DebugFormat("Collection cache hit: {0}", ck); } if (ce == null) { return false; } else { IPersistenceContext persistenceContext = source.PersistenceContext; CollectionCacheEntry cacheEntry = (CollectionCacheEntry)persister.CacheEntryStructure.Destructure(ce, factory); cacheEntry.Assemble(collection, persister, persistenceContext.GetCollectionOwner(id, persister)); persistenceContext.GetCollectionEntry(collection).PostInitialize(collection); return true; } } }
public override void Execute() { IEntityPersister persister = Persister; ISessionImplementor session = Session; object instance = Instance; object id = Id; bool veto = PreInsert(); // Don't need to lock the cache here, since if someone // else inserted the same pk first, the insert would fail if (!veto) { persister.Insert(id, state, instance, Session); EntityEntry entry = Session.PersistenceContext.GetEntry(instance); if (entry == null) { throw new AssertionFailure("Possible nonthreadsafe access to session"); } entry.PostInsert(); if (persister.HasInsertGeneratedProperties) { persister.ProcessInsertGeneratedProperties(id, instance, state, Session); if (persister.IsVersionPropertyGenerated) { version = Versioning.GetVersion(state, persister); } entry.PostUpdate(instance, state, version); } } ISessionFactoryImplementor factory = Session.Factory; if (IsCachePutEnabled(persister)) { CacheEntry ce = new CacheEntry(state, persister, persister.HasUninitializedLazyProperties(instance, session.EntityMode), version, session, instance); cacheEntry = persister.CacheEntryStructure.Structure(ce); CacheKey ck = new CacheKey(id, persister.IdentifierType, persister.RootEntityName, Session.EntityMode, Session.Factory); bool put = persister.Cache.Insert(ck, cacheEntry, version); if (put && factory.Statistics.IsStatisticsEnabled) { factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName); } } PostInsert(); if (factory.Statistics.IsStatisticsEnabled && !veto) { factory.StatisticsImplementor.InsertEntity(Persister.EntityName); } }
public object Get(CacheKey key, long timestamp) { object result = cache.Get(key); if (result != null && log.IsDebugEnabled) { log.Debug("Cache hit: " + key); } return result; }
/// <summary> /// Performs a pessimistic lock upgrade on a given entity, if needed. /// </summary> /// <param name="entity">The entity for which to upgrade the lock.</param> /// <param name="entry">The entity's EntityEntry instance.</param> /// <param name="requestedLockMode">The lock mode being requested for locking. </param> /// <param name="source">The session which is the source of the event being processed.</param> protected virtual void UpgradeLock(object entity, EntityEntry entry, LockMode requestedLockMode, ISessionImplementor source) { if (requestedLockMode.GreaterThan(entry.LockMode)) { // The user requested a "greater" (i.e. more restrictive) form of // pessimistic lock if (entry.Status != Status.Loaded) { throw new ObjectDeletedException("attempted to lock a deleted instance", entry.Id, entry.EntityName); } IEntityPersister persister = entry.Persister; if (log.IsDebugEnabled) { log.Debug(string.Format("locking {0} in mode: {1}", MessageHelper.InfoString(persister, entry.Id, source.Factory), requestedLockMode)); } ISoftLock slock; CacheKey ck; if (persister.HasCache) { ck = new CacheKey(entry.Id, persister.IdentifierType, persister.RootEntityName, source.EntityMode, source.Factory); slock = persister.Cache.Lock(ck, entry.Version); } else { ck = null; slock = null; } try { if (persister.IsVersioned && requestedLockMode == LockMode.Force) { // todo : should we check the current isolation mode explicitly? object nextVersion = persister.ForceVersionIncrement(entry.Id, entry.Version, source); entry.ForceLocked(entity, nextVersion); } else { persister.Lock(entry.Id, entry.Version, entity, requestedLockMode, source); } entry.LockMode = requestedLockMode; } finally { // the database now holds a lock + the object is flushed from the cache, // so release the soft lock if (persister.HasCache) { persister.Cache.Release(ck, slock); } } } }
public override void AfterTransactionCompletion(bool success) { if (Persister.HasCache) { CacheKey ck = new CacheKey(Id, Persister.IdentifierType, Persister.RootEntityName, Session.EntityMode, Session.Factory); Persister.Cache.Release(ck, sLock); } if (success) { PostCommitDelete(); } }
/// <summary></summary> public override void AfterTransactionCompletion(bool success) { if (Persister.HasCache) { CacheKey ck = new CacheKey( Id, Persister.IdentifierType, (string) Persister.IdentifierSpace, Session.Factory ); Persister.Cache.Release(ck, lck); } }
/// <summary></summary> public override void AfterTransactionCompletion(bool success) { // Make 100% certain that this is called before any subsequent ScheduledUpdate.AfterTransactionCompletion()!! if (success && Persister.HasCache && !Persister.IsCacheInvalidationRequired) { CacheKey ck = new CacheKey( Id, Persister.IdentifierType, (string) Persister.IdentifierSpace, Session.Factory ); Persister.Cache.AfterInsert(ck, cacheEntry, version); } }
/// <summary> /// Do not return an item whose timestamp is later than the current /// transaction timestamp. (Otherwise we might compromise repeatable /// read unnecessarily.) Do not return an item which is soft-locked. /// Always go straight to the database instead. /// </summary> /// <remarks> /// Note that since reading an item from that cache does not actually /// go to the database, it is possible to see a kind of phantom read /// due to the underlying row being updated after we have read it /// from the cache. This would not be possible in a lock-based /// implementation of repeatable read isolation. It is also possible /// to overwrite changes made and committed by another transaction /// after the current transaction read the item from the cache. This /// problem would be caught by the update-time version-checking, if /// the data is versioned or timestamped. /// </remarks> public object Get(CacheKey key, long txTimestamp) { lock (_lockObject) { if (log.IsDebugEnabled) { log.Debug("Cache lookup: " + key); } // commented out in H3.1 /*try { cache.Lock( key );*/ ILockable lockable = (ILockable) cache.Get(key); bool gettable = lockable != null && lockable.IsGettable(txTimestamp); if (gettable) { if (log.IsDebugEnabled) { log.Debug("Cache hit: " + key); } return ((CachedItem) lockable).Value; } else { if (log.IsDebugEnabled) { if (lockable == null) { log.Debug("Cache miss: " + key); } else { log.Debug("Cached item was locked: " + key); } } return null; } /*} finally { cache.Unlock( key ); }*/ } }
/// <summary></summary> public override void Execute() { if (Persister.HasCache) { CacheKey ck = new CacheKey( Id, Persister.IdentifierType, (string) Persister.IdentifierSpace, Session.Factory ); lck = Persister.Cache.Lock(ck, version); } Persister.Delete(Id, version, Instance, Session); Session.PostDelete(Instance); }
public void SecondLevelCachedCollectionsFiltering() { TestData testData = new TestData(this); testData.Prepare(); ISession session = OpenSession(); // Force a collection into the second level cache, with its non-filtered elements Salesperson sp = (Salesperson) session.Load(typeof(Salesperson), testData.steveId); NHibernateUtil.Initialize(sp.Orders); ICollectionPersister persister = ((ISessionFactoryImplementor) sessions) .GetCollectionPersister(typeof(Salesperson).FullName + ".Orders"); Assert.IsTrue(persister.HasCache, "No cache for collection"); CacheKey cacheKey = new CacheKey(testData.steveId, persister.KeyType, persister.Role, EntityMode.Poco, (ISessionFactoryImplementor) sessions); CollectionCacheEntry cachedData = (CollectionCacheEntry)persister.Cache.Cache.Get(cacheKey); Assert.IsNotNull(cachedData, "collection was not in cache"); session.Close(); session = OpenSession(); session.EnableFilter("fulfilledOrders").SetParameter("asOfDate", testData.lastMonth); sp = (Salesperson) session.CreateQuery("from Salesperson as s where s.id = :id") .SetInt64("id", testData.steveId) .UniqueResult(); Assert.AreEqual(1, sp.Orders.Count, "Filtered-collection not bypassing 2L-cache"); CollectionCacheEntry cachedData2 = (CollectionCacheEntry)persister.Cache.Cache.Get(cacheKey); Assert.IsNotNull(cachedData2, "collection no longer in cache!"); Assert.AreSame(cachedData, cachedData2, "Different cache values!"); session.Close(); session = OpenSession(); session.EnableFilter("fulfilledOrders").SetParameter("asOfDate", testData.lastMonth); sp = (Salesperson) session.Load(typeof(Salesperson), testData.steveId); Assert.AreEqual(1, sp.Orders.Count, "Filtered-collection not bypassing 2L-cache"); session.Close(); // Finally, make sure that the original cached version did not get over-written session = OpenSession(); sp = (Salesperson) session.Load(typeof(Salesperson), testData.steveId); Assert.AreEqual(2, sp.Orders.Count, "Actual cached version got over-written"); session.Close(); testData.Release(); }
/// <summary> /// Get the most recent version, if available. /// </summary> public object Get(CacheKey key, long txTimestamp) { if (log.IsDebugEnabled) { log.Debug("Cache lookup: " + key); } object result = cache.Get(key); if (result != null) { log.Debug("Cache hit"); } else { log.Debug("Cache miss"); } return result; }
public override void AfterTransactionCompletion(bool success) { //Make 100% certain that this is called before any subsequent ScheduledUpdate.afterTransactionCompletion()!! IEntityPersister persister = Persister; if (success && IsCachePutEnabled(persister)) { CacheKey ck = new CacheKey(Id, persister.IdentifierType, persister.RootEntityName, Session.EntityMode, Session.Factory); bool put = persister.Cache.AfterInsert(ck, cacheEntry, version); if (put && Session.Factory.Statistics.IsStatisticsEnabled) { Session.Factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName); } } if (success) { PostCommitInsert(); } }
/// <summary></summary> public override void Execute() { // Don't need to lock the cache here, since if someone // else inserted the same pk first, the insert would fail Persister.Insert(Id, state, Instance, Session); EntityEntry entry = Session.GetEntry(Instance); if (entry == null) { throw new AssertionFailure("possible nonthreadsafe access to session"); } entry.PostInsert(); if (Persister.HasInsertGeneratedProperties) { Persister.ProcessInsertGeneratedProperties(Id, Instance, state, Session); if (Persister.IsVersionPropertyGenerated) { version = Versioning.GetVersion(state, Persister); } entry.PostUpdate(Instance, state, version); } if (Persister.HasCache && !Persister.IsCacheInvalidationRequired) { cacheEntry = new CacheEntry(Instance, Persister, Session); CacheKey ck = new CacheKey( Id, Persister.IdentifierType, (string) Persister.IdentifierSpace, Session.Factory ); Persister.Cache.Insert(ck, cacheEntry); } }
public virtual void OnRefresh(RefreshEvent @event, IDictionary refreshedAlready) { IEventSource source = @event.Session; if (source.PersistenceContext.ReassociateIfUninitializedProxy(@event.Entity)) return; object obj = source.PersistenceContext.UnproxyAndReassociate(@event.Entity); if (refreshedAlready.Contains(obj)) { log.Debug("already refreshed"); return; } EntityEntry e = source.PersistenceContext.GetEntry(obj); IEntityPersister persister; object id; if (e == null) { persister = source.GetEntityPersister(null, obj); //refresh() does not pass an entityName id = persister.GetIdentifier(obj, source.EntityMode); if (log.IsDebugEnabled) { log.Debug("refreshing transient " + MessageHelper.InfoString(persister, id, source.Factory)); } EntityKey key = new EntityKey(id, persister, source.EntityMode); if (source.PersistenceContext.GetEntry(key) != null) { throw new PersistentObjectException("attempted to refresh transient instance when persistent instance was already associated with the Session: " + MessageHelper.InfoString(persister, id, source.Factory)); } } else { if (log.IsDebugEnabled) { log.Debug("refreshing " + MessageHelper.InfoString(e.Persister, e.Id, source.Factory)); } if (!e.ExistsInDatabase) { throw new HibernateException("this instance does not yet exist as a row in the database"); } persister = e.Persister; id = e.Id; } // cascade the refresh prior to refreshing this entity refreshedAlready[obj] = obj; new Cascade(CascadingAction.Refresh, CascadePoint.BeforeRefresh, source).CascadeOn(persister, obj, refreshedAlready); if (e != null) { EntityKey key = new EntityKey(id, persister, source.EntityMode); source.PersistenceContext.RemoveEntity(key); if (persister.HasCollections) new EvictVisitor(source).Process(obj, persister); } if (persister.HasCache) { CacheKey ck = new CacheKey(id, persister.IdentifierType, persister.RootEntityName, source.EntityMode, source.Factory); persister.Cache.Remove(ck); } EvictCachedCollections(persister, id, source.Factory); // NH Different behavior : NH-1601 // At this point the entity need the real refresh, all elementes of collections are Refreshed, // the collection state was evicted, but the PersistentCollection (in the entity state) // is associated with a possible previous session. new WrapVisitor(source).Process(obj, persister); string previousFetchProfile = source.FetchProfile; source.FetchProfile = "refresh"; object result = persister.Load(id, obj, @event.LockMode, source); source.FetchProfile = previousFetchProfile; // NH Different behavior : we are ignoring transient entities without throw any kind of exception // because a transient entity is "self refreshed" if (!ForeignKeys.IsTransient(persister.EntityName, obj, result == null, @event.Session)) UnresolvableObjectException.ThrowIfNull(result, id, persister.EntityName); }
public void EvictEntity(string entityName, object id) { IEntityPersister p = GetEntityPersister(entityName); if (p.HasCache) { if (log.IsDebugEnabled) { log.Debug("evicting second-level cache: " + MessageHelper.InfoString(p, id, this)); } CacheKey cacheKey = new CacheKey(id, p.IdentifierType, p.RootEntityName, EntityMode.Poco, this); p.Cache.Remove(cacheKey); } }
public void EvictCollection(string roleName, object id) { ICollectionPersister p = GetCollectionPersister(roleName); if (p.HasCache) { if (log.IsDebugEnabled) { log.Debug("evicting second-level cache: " + MessageHelper.InfoString(p, id)); } CacheKey ck = new CacheKey(id, p.KeyType, p.Role, EntityMode.Poco, this); p.Cache.Remove(ck); } }
/// <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> public static void InitializeEntity(object entity, bool readOnly, ISessionImplementor session, PreLoadEvent preLoadEvent, PostLoadEvent postLoadEvent) { //TODO: Should this be an InitializeEntityEventListener??? (watch out for performance!) 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 " + MessageHelper.InfoString(persister, id, session.Factory)); IType[] types = persister.PropertyTypes; for (int i = 0; i < hydratedState.Length; i++) { object value = hydratedState[i]; if (value != LazyPropertyInitializer.UnfetchedProperty && value != BackrefPropertyAccessor.Unknown) { hydratedState[i] = types[i].ResolveIdentifier(value, session, entity); } } //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++) { listeners[i].OnPreLoad(preLoadEvent); } } persister.SetPropertyValues(entity, hydratedState, session.EntityMode); ISessionFactoryImplementor factory = session.Factory; if (persister.HasCache && ((session.CacheMode & CacheMode.Put) == CacheMode.Put)) { if (log.IsDebugEnabled) log.Debug("adding entity to second-level cache: " + MessageHelper.InfoString(persister, id, session.Factory)); object version = Versioning.GetVersion(hydratedState, persister); CacheEntry entry = new CacheEntry(hydratedState, persister, entityEntry.LoadedWithLazyPropertiesUnfetched, version, session, entity); CacheKey cacheKey = new CacheKey(id, persister.IdentifierType, persister.RootEntityName, session.EntityMode, session.Factory); bool put = persister.Cache.Put(cacheKey, entry, session.Timestamp, version, persister.IsVersioned ? persister.VersionType.Comparator : null, UseMinimalPuts(session, entityEntry)); //we could use persister.hasLazyProperties() instead of true if (put && factory.Statistics.IsStatisticsEnabled) { factory.StatisticsImplementor.SecondLevelCachePut(persister.Cache.RegionName); } } if (readOnly || !persister.IsMutable) { //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 TypeFactory.DeepCopy(hydratedState, persister.PropertyTypes, persister.PropertyUpdateability, hydratedState, session); persistenceContext.SetEntryStatus(entityEntry, Status.Loaded); } persister.AfterInitialize(entity, entityEntry.LoadedWithLazyPropertiesUnfetched, 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 " + MessageHelper.InfoString(persister, id, session.Factory)); if (factory.Statistics.IsStatisticsEnabled) { factory.StatisticsImplementor.LoadEntity(persister.EntityName); } }
/// <summary> Add the collection to the second-level cache </summary> /// <param name="lce">The entry representing the collection to add </param> /// <param name="persister">The persister </param> private void AddCollectionToCache(LoadingCollectionEntry lce, ICollectionPersister persister) { ISessionImplementor session = LoadContext.PersistenceContext.Session; ISessionFactoryImplementor factory = session.Factory; if (log.IsDebugEnabled) { log.Debug("Caching collection: " + MessageHelper.InfoString(persister, lce.Key, factory)); } if (!(session.EnabledFilters.Count == 0) && persister.IsAffectedByEnabledFilters(session)) { // some filters affecting the collection are enabled on the session, so do not do the put into the cache. log.Debug("Refusing to add to cache due to enabled filters"); // todo : add the notion of enabled filters to the CacheKey to differentiate filtered collections from non-filtered; // but CacheKey is currently used for both collections and entities; would ideally need to define two separate ones; // currently this works in conjunction with the check on // DefaultInitializeCollectionEventHandler.initializeCollectionFromCache() (which makes sure to not read from // cache with enabled filters). return; // EARLY EXIT!!!!! } IComparer versionComparator; object version; if (persister.IsVersioned) { versionComparator = persister.OwnerEntityPersister.VersionType.Comparator; object collectionOwner = LoadContext.PersistenceContext.GetCollectionOwner(lce.Key, persister); version = LoadContext.PersistenceContext.GetEntry(collectionOwner).Version; } else { version = null; versionComparator = null; } CollectionCacheEntry entry = new CollectionCacheEntry(lce.Collection, persister); CacheKey cacheKey = new CacheKey(lce.Key, persister.KeyType, persister.Role, session.EntityMode, factory); bool put = persister.Cache.Put(cacheKey, persister.CacheEntryStructure.Structure(entry), session.Timestamp, version, versionComparator, factory.Settings.IsMinimalPutsEnabled && session.CacheMode != CacheMode.Refresh); if (put && factory.Statistics.IsStatisticsEnabled) { factory.StatisticsImplementor.SecondLevelCachePut(persister.Cache.RegionName); } }
/// <summary> /// Do nothing /// </summary> public ISoftLock Lock(CacheKey key, object version) { return null; }
public void Remove(CacheKey key) { if (log.IsDebugEnabled) { log.Debug("Removing: " + key); } cache.Remove(key); }
public virtual object InitializeLazyProperty(string fieldName, object entity, ISessionImplementor session) { object id = session.GetContextEntityIdentifier(entity); EntityEntry entry = session.PersistenceContext.GetEntry(entity); if (entry == null) throw new HibernateException("entity is not associated with the session: " + id); if (log.IsDebugEnabled) { log.Debug( string.Format("initializing lazy properties of: {0}, field access: {1}", MessageHelper.InfoString(this, id, Factory), fieldName)); } if (HasCache) { CacheKey cacheKey = new CacheKey(id, IdentifierType, EntityName, session.EntityMode, Factory); object ce = Cache.Get(cacheKey, session.Timestamp); if (ce != null) { CacheEntry cacheEntry = (CacheEntry)CacheEntryStructure.Destructure(ce, factory); if (!cacheEntry.AreLazyPropertiesUnfetched) { //note early exit here: return InitializeLazyPropertiesFromCache(fieldName, entity, session, entry, cacheEntry); } } } return InitializeLazyPropertiesFromDatastore(fieldName, entity, session, id, entry); }
/// <summary> /// Do nothing /// </summary> public bool AfterInsert(CacheKey key, object value, object version) { return false; }
/// <summary> /// Invalidate the item (again, for safety). /// </summary> public bool AfterUpdate(CacheKey key, object value, object version, ISoftLock @lock) { Release(key, @lock); return false; }
/// <summary> /// Invalidate the item (again, for safety). /// </summary> public void Release(CacheKey key, ISoftLock @lock) { if (log.IsDebugEnabled) { log.Debug("Invalidating (again): " + key); } cache.Remove(key); }
/// <summary> /// Do nothing /// </summary> public bool Insert(CacheKey key, object value, object currentVersion) { return false; }
public virtual bool? IsTransient(object entity, ISessionImplementor session) { object id; if (CanExtractIdOutOfEntity) { id = GetIdentifier(entity, session.EntityMode); } else { id = null; } // we *always* assume an instance with a null // identifier or no identifier property is unsaved! if (id == null) { return true; } // check the version unsaved-value, if appropriate if (IsVersioned) { object version = GetVersion(entity, session.EntityMode); // let this take precedence if defined, since it works for // assigned identifiers bool? result = entityMetamodel.VersionProperty.UnsavedValue.IsUnsaved(version); if (result.HasValue) { return result; } } // check the id unsaved-value bool? result2 = entityMetamodel.IdentifierProperty.UnsavedValue.IsUnsaved(id); if (result2.HasValue) return result2; // check to see if it is in the second-level cache if (HasCache) { CacheKey ck = new CacheKey(id, IdentifierType, RootEntityName, session.EntityMode, session.Factory); if (Cache.Get(ck, session.Timestamp) != null) return false; } return null; }
/// <summary> /// Invalidate the item /// </summary> public bool Update(CacheKey key, object value, object currentVersion, object previousVersion) { Evict(key); return false; }