Skip to content

NH-3087 pre-work #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/NHibernate.DomainModel/CustomPersister.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,8 @@ public object Load(object id, object optionalObject, LockMode lockMode, ISession
Custom obj = (Custom)Instances[id];
if (obj != null)
{
clone = (Custom)obj.Clone();
TwoPhaseLoad.AddUninitializedEntity(new EntityKey(id, this, session.EntityMode), clone, this, LockMode.None, false,
clone = (Custom)obj.Clone();
TwoPhaseLoad.AddUninitializedEntity(session.GenerateEntityKey(id, this), clone, this, LockMode.None, false,
session);
TwoPhaseLoad.PostHydrate(this, id, new String[] {obj.Name}, null, clone, LockMode.None, false, session);
TwoPhaseLoad.InitializeEntity(clone, false, session, new PreLoadEvent((IEventSource) session),
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate.Test/CacheTest/CacheFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void TestSimpleCache()

private CacheKey CreateCacheKey(string text)
{
return new CacheKey(text, NHibernateUtil.String, "Foo", EntityMode.Poco, null);
return new CacheKey(text, NHibernateUtil.String, "Foo", EntityMode.Poco, null, null);
}

public void DoTestCache(ICacheProvider cacheProvider)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate.Test/FilterTest/DynamicFilterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void SecondLevelCachedCollectionsFiltering()
.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);
new CacheKey(testData.steveId, persister.KeyType, persister.Role, EntityMode.Poco, null, (ISessionFactoryImplementor) sessions);
CollectionCacheEntry cachedData = (CollectionCacheEntry)persister.Cache.Cache.Get(cacheKey);
Assert.IsNotNull(cachedData, "collection was not in cache");

Expand Down
6 changes: 3 additions & 3 deletions src/NHibernate/Action/CollectionAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public virtual void BeforeExecutions()
// second-level cache invalidation only)
if (persister.HasCache)
{
CacheKey ck = new CacheKey(key, persister.KeyType, persister.Role, session.EntityMode, session.Factory);
CacheKey ck = session.GenerateCacheKey(key, persister.KeyType, persister.Role);
softLock = persister.Cache.Lock(ck, null);
}
}
Expand All @@ -120,7 +120,7 @@ public virtual AfterTransactionCompletionProcessDelegate AfterTransactionComplet
{
if (persister.HasCache)
{
CacheKey ck = new CacheKey(key, persister.KeyType, persister.Role, Session.EntityMode, Session.Factory);
CacheKey ck = Session.GenerateCacheKey(key, persister.KeyType, persister.Role);
persister.Cache.Release(ck, softLock);
}
});
Expand All @@ -138,7 +138,7 @@ protected internal void Evict()
{
if (persister.HasCache)
{
CacheKey ck = new CacheKey(key, persister.KeyType, persister.Role, session.EntityMode, session.Factory);
CacheKey ck = session.GenerateCacheKey(key, persister.KeyType, persister.Role);
persister.Cache.Evict(ck);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Action/CollectionUpdateAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public override AfterTransactionCompletionProcessDelegate AfterTransactionComple
// NH Different behavior: to support unlocking collections from the cache.(r3260)
if (Persister.HasCache)
{
CacheKey ck = new CacheKey(Key, Persister.KeyType, Persister.Role, Session.EntityMode, Session.Factory);
CacheKey ck = Session.GenerateCacheKey(Key, Persister.KeyType, Persister.Role);

if (success)
{
Expand Down
6 changes: 3 additions & 3 deletions src/NHibernate/Action/EntityDeleteAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public override void Execute()
CacheKey ck;
if (persister.HasCache)
{
ck = new CacheKey(id, persister.IdentifierType, persister.RootEntityName, session.EntityMode, session.Factory);
ck = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
sLock = persister.Cache.Lock(ck, version);
}
else
Expand All @@ -83,7 +83,7 @@ public override void Execute()
}
entry.PostDelete();

EntityKey key = new EntityKey(entry.Id, entry.Persister, session.EntityMode);
EntityKey key = session.GenerateEntityKey(entry.Id, entry.Persister);
persistenceContext.RemoveEntity(key);
persistenceContext.RemoveProxy(key);

Expand Down Expand Up @@ -131,7 +131,7 @@ protected override void AfterTransactionCompletionProcessImpl(bool success)
{
if (Persister.HasCache)
{
CacheKey ck = new CacheKey(Id, Persister.IdentifierType, Persister.RootEntityName, Session.EntityMode, Session.Factory);
CacheKey ck = Session.GenerateCacheKey(Id, Persister.IdentifierType, Persister.RootEntityName);
Persister.Cache.Release(ck, sLock);
}
if (success)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Action/EntityIdentityInsertAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private EntityKey GenerateDelayedEntityKey()
if (!isDelayed)
throw new HibernateException("Cannot request delayed entity-key for non-delayed post-insert-id generation");

return new EntityKey(new DelayedPostInsertIdentifier(), Persister, Session.EntityMode);
return Session.GenerateEntityKey(new DelayedPostInsertIdentifier(), Persister);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/NHibernate/Action/EntityInsertAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public override void Execute()
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);
CacheKey ck = Session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
bool put = persister.Cache.Insert(ck, cacheEntry, version);

if (put && factory.Statistics.IsStatisticsEnabled)
Expand All @@ -108,7 +108,7 @@ protected override void AfterTransactionCompletionProcessImpl(bool success)
IEntityPersister persister = Persister;
if (success && IsCachePutEnabled(persister))
{
CacheKey ck = new CacheKey(Id, persister.IdentifierType, persister.RootEntityName, Session.EntityMode, Session.Factory);
CacheKey ck = Session.GenerateCacheKey(Id, persister.IdentifierType, persister.RootEntityName);
bool put = persister.Cache.AfterInsert(ck, cacheEntry, version);

if (put && Session.Factory.Statistics.IsStatisticsEnabled)
Expand Down
4 changes: 2 additions & 2 deletions src/NHibernate/Action/EntityUpdateAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public override void Execute()
CacheKey ck = null;
if (persister.HasCache)
{
ck = new CacheKey(id, persister.IdentifierType, persister.RootEntityName, session.EntityMode, factory);
ck = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
slock = persister.Cache.Lock(ck, previousVersion);
}

Expand Down Expand Up @@ -140,7 +140,7 @@ protected override void AfterTransactionCompletionProcessImpl(bool success)
IEntityPersister persister = Persister;
if (persister.HasCache)
{
CacheKey ck = new CacheKey(Id, persister.IdentifierType, persister.RootEntityName, Session.EntityMode, Session.Factory);
CacheKey ck = Session.GenerateCacheKey(Id, persister.IdentifierType, persister.RootEntityName);

if (success && cacheEntry != null)
{
Expand Down
38 changes: 20 additions & 18 deletions src/NHibernate/Cache/CacheKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,27 @@ public class CacheKey
private readonly string entityOrRoleName;
private readonly int hashCode;
private readonly EntityMode entityMode;
private readonly string tenantId;

/// <summary>
/// Construct a new key for a collection or entity instance.
/// Note that an entity name should always be the root entity
/// name, not a subclass entity name.
/// </summary>
/// <param name="id">The identifier associated with the cached data </param>
/// <param name="type">The Hibernate type mapping </param>
/// <param name="entityOrRoleName">The entity or collection-role name. </param>
/// <param name="entityMode">The entiyt mode of the originating session </param>
/// <param name="factory">The session factory for which we are caching </param>
public CacheKey(object id, IType type, string entityOrRoleName, EntityMode entityMode, ISessionFactoryImplementor factory)
{
key = id;
this.type = type;
this.entityOrRoleName = entityOrRoleName;
this.entityMode = entityMode;
hashCode = type.GetHashCode(key, entityMode, factory);
}
/// <summary>
/// Construct a new key for a collection or entity instance.
/// Note that an entity name should always be the root entity
/// name, not a subclass entity name.
/// </summary>
/// <param name="id">The identifier associated with the cached data </param>
/// <param name="type">The Hibernate type mapping </param>
/// <param name="entityOrRoleName">The entity or collection-role name. </param>
/// <param name="entityMode">The entiyt mode of the originating session </param>
/// <param name="factory">The session factory for which we are caching </param>
public CacheKey(object id, IType type, string entityOrRoleName, EntityMode entityMode, string tenantId, ISessionFactoryImplementor factory)
{
key = id;
this.type = type;
this.entityOrRoleName = entityOrRoleName;
this.entityMode = entityMode;
this.tenantId = tenantId;
hashCode = type.GetHashCode(key, entityMode, factory);
}

//Mainly for SysCache and Memcache
public override String ToString()
Expand Down
3 changes: 3 additions & 0 deletions src/NHibernate/Cfg/Environment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ public static string Version
/// <summary>The EntityMode in which set the Session opened from the SessionFactory.</summary>
public const string DefaultEntityMode = "default_entity_mode";

/// <summary>The multi tenancy strategy to use</summary>
public const string MultiTenancyStrategy = "multi_tenancy_strategy";

/// <summary>
/// When using an enhanced id generator and pooled optimizers (<see cref="NHibernate.Id.Enhanced.IOptimizer"/>),
/// prefer interpreting the database value as the lower (lo) boundary. The default is to interpret it as the high boundary.
Expand Down
51 changes: 51 additions & 0 deletions src/NHibernate/Cfg/MultiTenancyStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

namespace NHibernate.Cfg
{
public enum MultiTenancyStrategy
{
/// <summary>
/// Multi-tenancy implemented by use of discriminator columns (i.e. tenantId)
/// </summary>
Discriminator,

/// <summary>
/// Tenant per-schema
/// </summary>
Schema,

/// <summary>
/// Tenant per-database
/// </summary>
Database,

/// <summary>
/// No multi-tenancy (default)
/// </summary>
None
}

public static class MultiTenancyStrategyParser
{
public const string DiscriminatorXmlName = "discriminator";
public const string SchemaXmlName = "per-schema";
public const string DatabaseXmlName = "per-database";
public const string NoneXmlName = "none";

public static MultiTenancyStrategy Convert(string value)
{
switch (value)
{
case NoneXmlName:
return MultiTenancyStrategy.None;
case SchemaXmlName:
throw new HibernateException("multi-tenancy strategies are not yet supported");
case DatabaseXmlName:
throw new HibernateException("multi-tenancy strategies are not yet supported");
case DiscriminatorXmlName:
throw new HibernateException("multi-tenancy strategies are not yet supported");
default:
throw new HibernateException(string.Format("unknown multi-tenancy strategy: {0}", value));
}
}
}
}
4 changes: 3 additions & 1 deletion src/NHibernate/Cfg/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ public Settings()

public string DefaultSchemaName { get; set; }

public string DefaultCatalogName { get; internal set; }
public string DefaultCatalogName { get; internal set; }

public MultiTenancyStrategy MultiTenancyStrategy { get; internal set; }

public string SessionFactoryName { get; internal set; }

Expand Down
7 changes: 6 additions & 1 deletion src/NHibernate/Cfg/SettingsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ public Settings BuildSettings(IDictionary<string, string> properties)
if (defaultCatalog != null)
log.Info("Default catalog: " + defaultCatalog);
settings.DefaultSchemaName = defaultSchema;
settings.DefaultCatalogName = defaultCatalog;
settings.DefaultCatalogName = defaultCatalog;

string multiTenancyStrategy = PropertiesHelper.GetString(
Environment.MultiTenancyStrategy, properties, MultiTenancyStrategyParser.NoneXmlName);
settings.MultiTenancyStrategy = MultiTenancyStrategyParser.Convert(multiTenancyStrategy);
log.Info("multi-tenancy strategy: " + multiTenancyStrategy);

int batchFetchSize = PropertiesHelper.GetInt32(Environment.DefaultBatchFetchSize, properties, 1);
log.Info("Default batch fetch size: " + batchFetchSize);
Expand Down
15 changes: 6 additions & 9 deletions src/NHibernate/Engine/BatchFetchQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public object[] GetCollectionBatch(ICollectionPersister collectionPersister, obj
end = i;
//checkForEnd = false;
}
else if (!IsCached(ce.LoadedKey, collectionPersister, entityMode))
else if (!IsCached(ce.LoadedKey, collectionPersister))
{
keys[i++] = ce.LoadedKey;
//count++;
Expand Down Expand Up @@ -220,7 +220,7 @@ public object[] GetEntityBatch(IEntityPersister persister,object id,int batchSiz
}
else
{
if (!IsCached(key, persister, entityMode))
if (!IsCached(key, persister))
{
ids[i++] = key.Identifier;
}
Expand All @@ -236,24 +236,21 @@ public object[] GetEntityBatch(IEntityPersister persister,object id,int batchSiz
return ids; //we ran out of ids to try
}

private bool IsCached(EntityKey entityKey, IEntityPersister persister, EntityMode entityMode)
private bool IsCached(EntityKey entityKey, IEntityPersister persister)
{
if (persister.HasCache)
{
CacheKey key =
new CacheKey(entityKey.Identifier, persister.IdentifierType, entityKey.EntityName, entityMode,
context.Session.Factory);
CacheKey key = context.Session.GenerateCacheKey(entityKey.Identifier, persister.IdentifierType, entityKey.EntityName);
return persister.Cache.Cache.Get(key) != null;
}
return false;
}

private bool IsCached(object collectionKey, ICollectionPersister persister, EntityMode entityMode)
private bool IsCached(object collectionKey, ICollectionPersister persister)
{
if (persister.HasCache)
{
CacheKey cacheKey =
new CacheKey(collectionKey, persister.KeyType, persister.Role, entityMode, context.Session.Factory);
CacheKey cacheKey = context.Session.GenerateCacheKey(collectionKey, persister.KeyType, persister.Role);
return persister.Cache.Cache.Get(cacheKey) != null;
}
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Engine/Collections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private static void ProcessDereferencedCollection(IPersistentCollection coll, IS
// throw new AssertionFailure("Unable to determine collection owner identifier for orphan-delete processing");
// }
//}
EntityKey key = new EntityKey(ownerId, loadedPersister.OwnerEntityPersister, session.EntityMode);
EntityKey key = session.GenerateEntityKey(ownerId, loadedPersister.OwnerEntityPersister);
object owner = persistenceContext.GetEntity(key);
if (owner == null)
{
Expand Down
Loading