Skip to content

Commit d0fe800

Browse files
itmaginationfredericDelaporte
authored andcommitted
Fix using Criteria and QuerOver for NH-3848
1 parent a251d32 commit d0fe800

File tree

11 files changed

+49
-30
lines changed

11 files changed

+49
-30
lines changed

src/NHibernate.Test/NHSpecificTest/NH3848/CriteriaTestFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected override IList<Customer> GetCustomersWithFetchedOrdersWithoutRestricti
1818
protected override IList<Customer> GetCustomersWithOrdersEagerLoaded(ISession session)
1919
{
2020
return session.CreateCriteria<Customer>()
21-
.SetFetchMode("Orders", FetchMode.Eager)
21+
.Fetch(SelectMode.Fetch, "Orders")
2222
.SetResultTransformer(new DistinctRootEntityResultTransformer())
2323
.List<Customer>();
2424
}

src/NHibernate.Test/NHSpecificTest/NH3848/QueryOverTestFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ protected override IList<Customer> GetCustomersWithFetchedOrdersWithoutRestricti
2121
protected override IList<Customer> GetCustomersWithOrdersEagerLoaded(ISession session)
2222
{
2323
return session.QueryOver<Customer>()
24-
.Fetch(n => n.Orders).Eager
24+
.Fetch(SelectMode.Fetch, n => n.Orders)
2525
.TransformUsing(new DistinctRootEntityResultTransformer())
2626
.List();
2727
}

src/NHibernate.Test/NHSpecificTest/NH3848/TestFixture.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,12 @@ public void ChildCollectionsFromLeftOuterJoinShouldBeInSecondLevelCacheIfQueryCo
235235
protected void ClearSecondLevelCacheFor(System.Type entity)
236236
{
237237
var entityName = entity.FullName;
238-
sessions.EvictEntity(entityName);
239-
var entityPersister = sessions.GetEntityPersister(entityName);
238+
Sfi.EvictEntity(entityName);
239+
var entityPersister = Sfi.GetEntityPersister(entityName);
240240
if (!entityPersister.HasCache)
241241
return;
242242

243-
var querySpaces = entityPersister.QuerySpaces.Cast<object>().ToArray();
244-
sessions.UpdateTimestampsCache.Invalidate(querySpaces);
243+
Sfi.UpdateTimestampsCache.PreInvalidate(entityPersister.QuerySpaces.ToList());
245244
}
246245

247246
protected void ClearCollectionCache<T>(Expression<Func<T, IEnumerable>> pathToCollection)
@@ -252,7 +251,7 @@ protected void ClearCollectionCache<T>(Expression<Func<T, IEnumerable>> pathToCo
252251
throw new ArgumentException("pathToCollection should be member expression");
253252

254253
var role = string.Format("{0}.{1}", rootEntityTypeFullPath, memberExpression.Member.Name);
255-
sessions.EvictCollection(role);
254+
Sfi.EvictCollection(role);
256255
}
257256

258257
protected abstract IList<Customer> GetCustomersWithFetchedOrdersWithoutRestrictions(ISession session);

src/NHibernate/Engine/Loading/CollectionLoadContext.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ public IPersistentCollection GetLoadingCollection(ICollectionPersister persister
145145
/// complete.
146146
/// </summary>
147147
/// <param name="persister">The persister for which to complete loading. </param>
148-
public void EndLoadingCollections(ICollectionPersister persister)
148+
/// <param name="canAddCollectionsToCache">Indicates if collcetion can be put in cache</param>
149+
public void EndLoadingCollections(ICollectionPersister persister, bool canAddCollectionsToCache)
149150
{
150151
if (!loadContexts.HasLoadingCollectionEntries && (localLoadingCollectionKeys.Count == 0))
151152
{
@@ -190,7 +191,7 @@ public void EndLoadingCollections(ICollectionPersister persister)
190191
}
191192
localLoadingCollectionKeys.ExceptWith(toRemove);
192193

193-
EndLoadingCollections(persister, matches);
194+
EndLoadingCollections(persister, matches, canAddCollectionsToCache);
194195
if ((localLoadingCollectionKeys.Count == 0))
195196
{
196197
// todo : hack!!!
@@ -203,7 +204,7 @@ public void EndLoadingCollections(ICollectionPersister persister)
203204
}
204205
}
205206

206-
private void EndLoadingCollections(ICollectionPersister persister, IList<LoadingCollectionEntry> matchedCollectionEntries)
207+
private void EndLoadingCollections(ICollectionPersister persister, IList<LoadingCollectionEntry> matchedCollectionEntries, bool canAddCollectionsToCache)
207208
{
208209
if (matchedCollectionEntries == null || matchedCollectionEntries.Count == 0)
209210
{
@@ -224,7 +225,7 @@ private void EndLoadingCollections(ICollectionPersister persister, IList<Loading
224225
for (int i = 0; i < count; i++)
225226
{
226227
EndLoadingCollection(matchedCollectionEntries[i], persister,
227-
data => cacheBatcher.AddToBatch(persister, data));
228+
data => cacheBatcher.AddToBatch(persister, data), canAddCollectionsToCache);
228229
}
229230
cacheBatcher.ExecuteBatch();
230231

@@ -235,7 +236,7 @@ private void EndLoadingCollections(ICollectionPersister persister, IList<Loading
235236
}
236237

237238
private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersister persister,
238-
Action<CachePutData> cacheBatchingHandler)
239+
Action<CachePutData> cacheBatchingHandler, bool canAddCollectionsToCache)
239240
{
240241
if (log.IsDebugEnabled())
241242
{
@@ -269,7 +270,7 @@ private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersist
269270
ce.PostInitialize(lce.Collection, persistenceContext);
270271
}
271272

272-
bool addToCache = hasNoQueuedOperations && persister.HasCache &&
273+
bool addToCache = canAddCollectionsToCache && hasNoQueuedOperations && persister.HasCache &&
273274
session.CacheMode.HasFlag(CacheMode.Put) && !ce.IsDoremove; // and this is not a forced initialization during flush
274275

275276
if (addToCache)

src/NHibernate/Engine/QueryParameters.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,28 @@ public QueryParameters(IType[] positionalParameterTypes, object[] postionalParam
3737
: this(positionalParameterTypes, postionalParameterValues, null, collectionKeys) {}
3838

3939
public QueryParameters(IType[] positionalParameterTypes, object[] postionalParameterValues, IDictionary<string, TypedValue> namedParameters, object[] collectionKeys)
40-
: this(positionalParameterTypes, postionalParameterValues, namedParameters, null, null, false, false, false, null, null, collectionKeys, null) {}
40+
: this(positionalParameterTypes, postionalParameterValues, namedParameters, null, null, false, false, false, null, null, collectionKeys, null, true) {}
4141

4242
public QueryParameters(IType[] positionalParameterTypes, object[] positionalParameterValues, IDictionary<string, LockMode> lockModes, RowSelection rowSelection,
4343
bool isReadOnlyInitialized, bool readOnly, bool cacheable, string cacheRegion, string comment, bool isLookupByNaturalKey, IResultTransformer transformer)
44-
: this(positionalParameterTypes, positionalParameterValues, null, lockModes, rowSelection, isReadOnlyInitialized, readOnly, cacheable, cacheRegion, comment, null, transformer)
44+
: this(positionalParameterTypes, positionalParameterValues, null, lockModes, rowSelection, isReadOnlyInitialized, readOnly, cacheable, cacheRegion, comment, null, transformer, true)
4545
{
4646
NaturalKeyLookup = isLookupByNaturalKey;
4747
}
4848

4949
public QueryParameters(IDictionary<string, TypedValue> namedParameters, IDictionary<string, LockMode> lockModes, RowSelection rowSelection, bool isReadOnlyInitialized,
50-
bool readOnly, bool cacheable, string cacheRegion, string comment, bool isLookupByNaturalKey, IResultTransformer transformer)
50+
bool readOnly, bool cacheable, string cacheRegion, string comment, bool isLookupByNaturalKey, IResultTransformer transformer, bool canAddCollectionsToCache)
5151
: this(
5252
TypeHelper.EmptyTypeArray, Array.Empty<object>(), namedParameters, lockModes, rowSelection, isReadOnlyInitialized, readOnly, cacheable, cacheRegion, comment, null,
53-
transformer)
53+
transformer, canAddCollectionsToCache)
5454
{
5555
// used by CriteriaTranslator
5656
NaturalKeyLookup = isLookupByNaturalKey;
5757
}
5858

5959
public QueryParameters(IType[] positionalParameterTypes, object[] positionalParameterValues, IDictionary<string, TypedValue> namedParameters,
6060
IDictionary<string, LockMode> lockModes, RowSelection rowSelection, bool isReadOnlyInitialized, bool readOnly, bool cacheable, string cacheRegion,
61-
string comment, object[] collectionKeys, IResultTransformer transformer)
61+
string comment, object[] collectionKeys, IResultTransformer transformer, bool canAddCollectionsToCache)
6262
{
6363
PositionalParameterTypes = positionalParameterTypes ?? Array.Empty<IType>();
6464
PositionalParameterValues = positionalParameterValues ?? Array.Empty<object>();
@@ -72,14 +72,15 @@ public QueryParameters(IType[] positionalParameterTypes, object[] positionalPara
7272
IsReadOnlyInitialized = isReadOnlyInitialized;
7373
this.readOnly = readOnly;
7474
ResultTransformer = transformer;
75+
CanAddCollectionsToCache = canAddCollectionsToCache;
7576
}
7677

7778
public QueryParameters(IType[] positionalParameterTypes, object[] positionalParameterValues, IDictionary<string, TypedValue> namedParameters,
7879
IDictionary<string, LockMode> lockModes, RowSelection rowSelection, bool isReadOnlyInitialized, bool readOnly, bool cacheable, string cacheRegion,
7980
string comment, object[] collectionKeys, object optionalObject, string optionalEntityName, object optionalId, IResultTransformer transformer)
8081
: this(
8182
positionalParameterTypes, positionalParameterValues, namedParameters, lockModes, rowSelection, isReadOnlyInitialized, readOnly, cacheable, cacheRegion, comment, collectionKeys,
82-
transformer)
83+
transformer, true)
8384
{
8485
OptionalEntityName = optionalEntityName;
8586
OptionalId = optionalId;
@@ -139,6 +140,11 @@ public bool HasRowSelection
139140

140141
public bool Callable { get; set; }
141142

143+
/// <summary>
144+
/// Indicates if we can add loaded child collections to second lvl cache.
145+
/// </summary>
146+
public bool CanAddCollectionsToCache { get; set; }
147+
142148
public bool ReadOnly
143149
{
144150
get

src/NHibernate/Impl/CriteriaImpl.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,7 @@ public sealed partial class Subcriteria : ICriteria, ISupportSelectModeCriteria
688688
private LockMode lockMode;
689689
private readonly JoinType joinType;
690690
private ICriterion withClause;
691+
private bool hasRestrictions;
691692

692693
internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string alias, JoinType joinType, ICriterion withClause, string joinEntityName = null)
693694
{
@@ -698,6 +699,7 @@ internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string al
698699
this.joinType = joinType;
699700
this.withClause = withClause;
700701
JoinEntityName = joinEntityName;
702+
hasRestrictions = withClause != null;
701703

702704
root.subcriteriaList.Add(this);
703705

@@ -731,6 +733,11 @@ public string Path
731733
get { return path; }
732734
}
733735

736+
public bool HasRestrictions
737+
{
738+
get { return hasRestrictions; }
739+
}
740+
734741
public ICriteria Parent
735742
{
736743
get { return parent; }
@@ -770,6 +777,7 @@ public ICriteria SetLockMode(LockMode lockMode)
770777

771778
public ICriteria Add(ICriterion expression)
772779
{
780+
hasRestrictions = true;
773781
root.Add(this, expression);
774782
return this;
775783
}

src/NHibernate/Impl/MultiCriteriaImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ private void GetResultsFromDatabase(IList results)
273273
for (int i = 0; i < loaders.Count; i++)
274274
{
275275
CriteriaLoader loader = loaders[i];
276-
loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, session.DefaultReadOnly);
276+
loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, session.DefaultReadOnly, null, parameters[i].CanAddCollectionsToCache);
277277

278278
if (createSubselects[i])
279279
{

src/NHibernate/Impl/MultiQueryImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ protected List<object> DoList()
616616
ITranslator translator = translators[i];
617617
QueryParameters parameter = parameters[i];
618618

619-
translator.Loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, false);
619+
translator.Loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, false, null, parameters[i].CanAddCollectionsToCache);
620620

621621
if (createSubselects[i])
622622
{

src/NHibernate/Loader/Criteria/CriteriaLoader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected override bool IsChildFetchEntity(int i)
9494

9595
public IList List(ISessionImplementor session)
9696
{
97-
return List(session, translator.GetQueryParameters(), querySpaces);
97+
return List(session, translator.GetQueryParameters(), querySpaces);
9898
}
9999

100100
protected override IResultTransformer ResolveResultTransformer(IResultTransformer resultTransformer)

src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ public QueryParameters GetQueryParameters()
139139
selection.FetchSize = rootCriteria.FetchSize;
140140

141141
var lockModes = new Dictionary<string, LockMode>();
142+
var canAddCollectionsToCache = true;
142143
foreach (KeyValuePair<string, LockMode> me in rootCriteria.LockModes)
143144
{
144145
ICriteria subcriteria = GetAliasedCriteria(me.Key);
@@ -152,6 +153,9 @@ public QueryParameters GetQueryParameters()
152153
{
153154
lockModes[GetSQLAlias(subcriteria)] = lm;
154155
}
156+
157+
if (subcriteria.HasRestrictions && subcriteria.JoinType == JoinType.LeftOuterJoin)
158+
canAddCollectionsToCache = false;
155159
}
156160

157161
IDictionary<string, TypedValue> queryNamedParameters = CollectedParameters.ToDictionary(np => np.Name, np => new TypedValue(np.Type, np.Value));
@@ -167,7 +171,8 @@ public QueryParameters GetQueryParameters()
167171
rootCriteria.CacheRegion,
168172
rootCriteria.Comment,
169173
rootCriteria.LookupByNaturalKey,
170-
rootCriteria.ResultTransformer)
174+
rootCriteria.ResultTransformer,
175+
canAddCollectionsToCache)
171176
{
172177
CacheMode = rootCriteria.CacheMode
173178
};

src/NHibernate/Loader/Loader.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ protected object LoadSingleRow(DbDataReader resultSet, ISessionImplementor sessi
315315
queryParameters.NamedParameters);
316316
}
317317

318-
InitializeEntitiesAndCollections(hydratedObjects, resultSet, session, queryParameters.IsReadOnly(session));
318+
InitializeEntitiesAndCollections(hydratedObjects, resultSet, session, queryParameters.IsReadOnly(session), null, queryParameters.CanAddCollectionsToCache);
319319
session.PersistenceContext.InitializeNonLazyCollections();
320320
return result;
321321
}
@@ -517,7 +517,7 @@ private IList DoQuery(ISessionImplementor session, QueryParameters queryParamete
517517
session.Batcher.CloseCommand(st, rs);
518518
}
519519

520-
InitializeEntitiesAndCollections(hydratedObjects, rs, session, queryParameters.IsReadOnly(session));
520+
InitializeEntitiesAndCollections(hydratedObjects, rs, session, queryParameters.IsReadOnly(session), null, queryParameters.CanAddCollectionsToCache);
521521

522522
if (createSubselects)
523523
{
@@ -601,7 +601,7 @@ private IEnumerable<SubselectFetch> CreateSubselects(IList<EntityKey[]> keys, Qu
601601

602602
internal void InitializeEntitiesAndCollections(
603603
IList hydratedObjects, object resultSetId, ISessionImplementor session, bool readOnly,
604-
CacheBatcher cacheBatcher = null)
604+
CacheBatcher cacheBatcher = null, bool canAddCollectionsToCache = true)
605605
{
606606
ICollectionPersister[] collectionPersisters = CollectionPersisters;
607607
if (collectionPersisters != null)
@@ -615,7 +615,7 @@ internal void InitializeEntitiesAndCollections(
615615
//during loading
616616
//TODO: or we could do this polymorphically, and have two
617617
// different operations implemented differently for arrays
618-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
618+
EndCollectionLoad(resultSetId, session, collectionPersisters[i], canAddCollectionsToCache);
619619
}
620620
}
621621
}
@@ -666,17 +666,17 @@ internal void InitializeEntitiesAndCollections(
666666
//the entities, since we might call hashCode() on the elements
667667
//TODO: or we could do this polymorphically, and have two
668668
// different operations implemented differently for arrays
669-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
669+
EndCollectionLoad(resultSetId, session, collectionPersisters[i], canAddCollectionsToCache);
670670
}
671671
}
672672
}
673673
}
674674

675-
private static void EndCollectionLoad(object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister)
675+
private static void EndCollectionLoad(object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister, bool canAddCollectionsToCache)
676676
{
677677
//this is a query and we are loading multiple instances of the same collection role
678678
session.PersistenceContext.LoadContexts.GetCollectionLoadContext((DbDataReader)resultSetId).EndLoadingCollections(
679-
collectionPersister);
679+
collectionPersister, canAddCollectionsToCache);
680680
}
681681

682682

0 commit comments

Comments
 (0)