Skip to content

Commit d903bb2

Browse files
Guards against use of a disposed session factory (#3120)
This would enable to help diagnose #3026 complaints
1 parent 86d2930 commit d903bb2

File tree

4 files changed

+79
-2
lines changed

4 files changed

+79
-2
lines changed

src/NHibernate.Test/Async/SessionBuilder/Fixture.cs

+17
Original file line numberDiff line numberDiff line change
@@ -227,5 +227,22 @@ private void CanSetOnStateless<T, V>(
227227
Assert.AreEqual(sb, fsb, $"{sbType}: Unexpected fluent return after call with {value}");
228228
}
229229
}
230+
231+
[Test]
232+
public void ThrowWhenUsingSessionFromDisposedFactoryAsync()
233+
{
234+
using (var session = Sfi.OpenSession())
235+
{
236+
try
237+
{
238+
Sfi.Dispose();
239+
Assert.That(() => session.GetAsync<Entity>(Guid.Empty), Throws.InstanceOf(typeof(ObjectDisposedException)));
240+
}
241+
finally
242+
{
243+
RebuildSessionFactory();
244+
}
245+
}
246+
}
230247
}
231248
}

src/NHibernate.Test/SessionBuilder/Fixture.cs

+31
Original file line numberDiff line numberDiff line change
@@ -298,5 +298,36 @@ private void CanSetOnStateless<T, V>(
298298
Assert.AreEqual(sb, fsb, $"{sbType}: Unexpected fluent return after call with {value}");
299299
}
300300
}
301+
302+
[Test]
303+
public void ThrowWhenOpeningFromDisposedFactory()
304+
{
305+
try
306+
{
307+
Sfi.Dispose();
308+
Assert.That(Sfi.OpenSession, Throws.InstanceOf(typeof(ObjectDisposedException)));
309+
}
310+
finally
311+
{
312+
RebuildSessionFactory();
313+
}
314+
}
315+
316+
[Test]
317+
public void ThrowWhenUsingSessionFromDisposedFactory()
318+
{
319+
using (var session = Sfi.OpenSession())
320+
{
321+
try
322+
{
323+
Sfi.Dispose();
324+
Assert.That(() => session.Get<Entity>(Guid.Empty), Throws.InstanceOf(typeof(ObjectDisposedException)));
325+
}
326+
finally
327+
{
328+
RebuildSessionFactory();
329+
}
330+
}
331+
}
301332
}
302333
}

src/NHibernate/Async/Impl/SessionFactoryImpl.cs

+2
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ async Task InternalEvictCollectionAsync()
353353
// NH Different implementation
354354
if (queryCache != null)
355355
{
356+
CheckNotClosed();
356357
await (queryCache.ClearAsync(cancellationToken)).ConfigureAwait(false);
357358
if (queryCaches.Count == 0)
358359
{
@@ -377,6 +378,7 @@ async Task InternalEvictCollectionAsync()
377378
{
378379
if (settings.IsQueryCacheEnabled)
379380
{
381+
CheckNotClosed();
380382
if (queryCaches.TryGetValue(cacheRegion, out var currentQueryCache))
381383
{
382384
return currentQueryCache.Value.ClearAsync(cancellationToken);

src/NHibernate/Impl/SessionFactoryImpl.cs

+29-2
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,11 @@ private ICacheConcurrencyStrategy GetCacheConcurrencyStrategy(
469469

470470
public EventListeners EventListeners
471471
{
472-
get { return eventListeners; }
472+
get
473+
{
474+
CheckNotClosed();
475+
return eventListeners;
476+
}
473477
}
474478

475479
#region IObjectReference Members
@@ -513,6 +517,7 @@ public object GetRealObject(StreamingContext context)
513517

514518
public ISessionBuilder WithOptions()
515519
{
520+
CheckNotClosed();
516521
return new SessionBuilderImpl(this);
517522
}
518523

@@ -563,6 +568,7 @@ public ISession OpenSession(DbConnection connection, bool flushBeforeCompletionE
563568

564569
public IStatelessSessionBuilder WithStatelessOptions()
565570
{
571+
CheckNotClosed();
566572
return new StatelessSessionBuilderImpl(this);
567573
}
568574

@@ -580,6 +586,7 @@ public IStatelessSession OpenStatelessSession(DbConnection connection)
580586

581587
public IEntityPersister GetEntityPersister(string entityName)
582588
{
589+
CheckNotClosed();
583590
IEntityPersister value;
584591
if (entityPersisters.TryGetValue(entityName, out value) == false)
585592
throw new MappingException("No persister for: " + entityName);
@@ -588,13 +595,15 @@ public IEntityPersister GetEntityPersister(string entityName)
588595

589596
public IEntityPersister TryGetEntityPersister(string entityName)
590597
{
598+
CheckNotClosed();
591599
IEntityPersister result;
592600
entityPersisters.TryGetValue(entityName, out result);
593601
return result;
594602
}
595603

596604
public ICollectionPersister GetCollectionPersister(string role)
597605
{
606+
CheckNotClosed();
598607
ICollectionPersister value;
599608
if (collectionPersisters.TryGetValue(role, out value) == false)
600609
throw new MappingException("Unknown collection role: " + role);
@@ -863,6 +872,14 @@ public void Dispose()
863872
Close();
864873
}
865874

875+
private void CheckNotClosed()
876+
{
877+
if (isClosed)
878+
{
879+
throw new ObjectDisposedException($"Session factory {Name} with id {Uuid}");
880+
}
881+
}
882+
866883
/// <summary>
867884
/// Closes the session factory, releasing all held resources.
868885
/// <list>
@@ -1105,6 +1122,7 @@ public UpdateTimestampsCache UpdateTimestampsCache
11051122
public IDictionary<string, ICache> GetAllSecondLevelCacheRegions()
11061123
#pragma warning restore 618
11071124
{
1125+
CheckNotClosed();
11081126
return
11091127
_allCacheRegions
11101128
// ToArray creates a moment in time snapshot
@@ -1119,6 +1137,7 @@ public IDictionary<string, ICache> GetAllSecondLevelCacheRegions()
11191137
public ICache GetSecondLevelCacheRegion(string regionName)
11201138
#pragma warning restore 618
11211139
{
1140+
CheckNotClosed();
11221141
_allCacheRegions.TryGetValue(regionName, out var result);
11231142
return result;
11241143
}
@@ -1145,7 +1164,12 @@ public IStatisticsImplementor StatisticsImplementor
11451164

11461165
public IQueryCache QueryCache
11471166
{
1148-
get { return queryCache; }
1167+
get
1168+
{
1169+
if (queryCache != null)
1170+
CheckNotClosed();
1171+
return queryCache;
1172+
}
11491173
}
11501174

11511175
public IQueryCache GetQueryCache(string cacheRegion)
@@ -1159,6 +1183,7 @@ public IQueryCache GetQueryCache(string cacheRegion)
11591183
return null;
11601184
}
11611185

1186+
CheckNotClosed();
11621187
// The factory may be run concurrently by threads trying to get the same region.
11631188
// But the GetOrAdd will yield the same lazy for all threads, so only one will
11641189
// initialize. https://stackoverflow.com/a/31637510/1178314
@@ -1175,6 +1200,7 @@ public void EvictQueries()
11751200
// NH Different implementation
11761201
if (queryCache != null)
11771202
{
1203+
CheckNotClosed();
11781204
queryCache.Clear();
11791205
if (queryCaches.Count == 0)
11801206
{
@@ -1193,6 +1219,7 @@ public void EvictQueries(string cacheRegion)
11931219
{
11941220
if (settings.IsQueryCacheEnabled)
11951221
{
1222+
CheckNotClosed();
11961223
if (queryCaches.TryGetValue(cacheRegion, out var currentQueryCache))
11971224
{
11981225
currentQueryCache.Value.Clear();

0 commit comments

Comments
 (0)