Skip to content

Commit 2d5245a

Browse files
committed
Fix using Criteria and QuerOver for NH-3848
1 parent 6ccab2a commit 2d5245a

File tree

8 files changed

+43
-23
lines changed

8 files changed

+43
-23
lines changed

src/NHibernate/Engine/Loading/CollectionLoadContext.cs

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

191-
EndLoadingCollections(persister, matches);
192+
EndLoadingCollections(persister, matches, canAddCollectionsToCache);
192193
if ((localLoadingCollectionKeys.Count == 0))
193194
{
194195
// todo : hack!!!
@@ -201,7 +202,7 @@ public void EndLoadingCollections(ICollectionPersister persister)
201202
}
202203
}
203204

204-
private void EndLoadingCollections(ICollectionPersister persister, IList<LoadingCollectionEntry> matchedCollectionEntries)
205+
private void EndLoadingCollections(ICollectionPersister persister, IList<LoadingCollectionEntry> matchedCollectionEntries, bool canAddCollectionsToCache)
205206
{
206207
if (matchedCollectionEntries == null || matchedCollectionEntries.Count == 0)
207208
{
@@ -220,7 +221,7 @@ private void EndLoadingCollections(ICollectionPersister persister, IList<Loading
220221

221222
for (int i = 0; i < count; i++)
222223
{
223-
EndLoadingCollection(matchedCollectionEntries[i], persister);
224+
EndLoadingCollection(matchedCollectionEntries[i], persister, canAddCollectionsToCache);
224225
}
225226

226227
if (log.IsDebugEnabled)
@@ -229,7 +230,7 @@ private void EndLoadingCollections(ICollectionPersister persister, IList<Loading
229230
}
230231
}
231232

232-
private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersister persister)
233+
private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersister persister, bool canAddCollectionsToCache)
233234
{
234235
if (log.IsDebugEnabled)
235236
{
@@ -262,7 +263,7 @@ private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersist
262263
ce.PostInitialize(lce.Collection);
263264
}
264265

265-
bool addToCache = hasNoQueuedAdds && persister.HasCache &&
266+
bool addToCache = canAddCollectionsToCache && hasNoQueuedAdds && persister.HasCache &&
266267
((session.CacheMode & CacheMode.Put) == CacheMode.Put) && !ce.IsDoremove; // and this is not a forced initialization during flush
267268

268269
if (addToCache)

src/NHibernate/Engine/QueryParameters.cs

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

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

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

5050
public QueryParameters(IDictionary<string, TypedValue> namedParameters, IDictionary<string, LockMode> lockModes, RowSelection rowSelection, bool isReadOnlyInitialized,
51-
bool readOnly, bool cacheable, string cacheRegion, string comment, bool isLookupByNaturalKey, IResultTransformer transformer)
51+
bool readOnly, bool cacheable, string cacheRegion, string comment, bool isLookupByNaturalKey, IResultTransformer transformer, bool canAddCollectionsToCache)
5252
: this(
5353
TypeHelper.EmptyTypeArray, ArrayHelper.EmptyObjectArray, namedParameters, lockModes, rowSelection, isReadOnlyInitialized, readOnly, cacheable, cacheRegion, comment, null,
54-
transformer)
54+
transformer, canAddCollectionsToCache)
5555
{
5656
// used by CriteriaTranslator
5757
NaturalKeyLookup = isLookupByNaturalKey;
5858
}
5959

6060
public QueryParameters(IType[] positionalParameterTypes, object[] positionalParameterValues, IDictionary<string, TypedValue> namedParameters,
6161
IDictionary<string, LockMode> lockModes, RowSelection rowSelection, bool isReadOnlyInitialized, bool readOnly, bool cacheable, string cacheRegion,
62-
string comment, object[] collectionKeys, IResultTransformer transformer)
62+
string comment, object[] collectionKeys, IResultTransformer transformer, bool canAddCollectionsToCache)
6363
{
6464
PositionalParameterTypes = positionalParameterTypes ?? new IType[0];
6565
PositionalParameterValues = positionalParameterValues ?? new object[0];
@@ -73,14 +73,15 @@ public QueryParameters(IType[] positionalParameterTypes, object[] positionalPara
7373
IsReadOnlyInitialized = isReadOnlyInitialized;
7474
this.readOnly = readOnly;
7575
ResultTransformer = transformer;
76+
CanAddCollectionsToCache = canAddCollectionsToCache;
7677
}
7778

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

139140
public bool Callable { get; set; }
140141

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

src/NHibernate/Impl/CriteriaImpl.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ public sealed class Subcriteria : ICriteria
645645
private LockMode lockMode;
646646
private readonly JoinType joinType;
647647
private ICriterion withClause;
648+
private bool hasRestrictions;
648649

649650
internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string alias, JoinType joinType, ICriterion withClause)
650651
{
@@ -654,6 +655,7 @@ internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string al
654655
this.path = path;
655656
this.joinType = joinType;
656657
this.withClause = withClause;
658+
hasRestrictions = withClause != null;
657659

658660
root.subcriteriaList.Add(this);
659661

@@ -677,6 +679,11 @@ public string Path
677679
get { return path; }
678680
}
679681

682+
public bool HasRestrictions
683+
{
684+
get { return hasRestrictions; }
685+
}
686+
680687
public ICriteria Parent
681688
{
682689
get { return parent; }
@@ -716,6 +723,7 @@ public ICriteria SetLockMode(LockMode lockMode)
716723

717724
public ICriteria Add(ICriterion expression)
718725
{
726+
hasRestrictions = true;
719727
root.Add(this, expression);
720728
return this;
721729
}

src/NHibernate/Impl/MultiCriteriaImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ private void GetResultsFromDatabase(IList results)
266266
for (int i = 0; i < loaders.Count; i++)
267267
{
268268
CriteriaLoader loader = loaders[i];
269-
loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, session.DefaultReadOnly);
269+
loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, session.DefaultReadOnly, parameters[i].CanAddCollectionsToCache);
270270

271271
if (createSubselects[i])
272272
{

src/NHibernate/Impl/MultiQueryImpl.cs

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

600-
translator.Loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, false);
600+
translator.Loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, false, parameters[i].CanAddCollectionsToCache);
601601

602602
if (createSubselects[i])
603603
{

src/NHibernate/Loader/Criteria/CriteriaLoader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ protected override bool[] IncludeInResultRow
8686

8787
public IList List(ISessionImplementor session)
8888
{
89-
return List(session, translator.GetQueryParameters(), querySpaces, resultTypes);
89+
return List(session, translator.GetQueryParameters(), querySpaces, resultTypes);
9090
}
9191

9292
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
@@ -121,6 +121,7 @@ public QueryParameters GetQueryParameters()
121121
selection.FetchSize = rootCriteria.FetchSize;
122122

123123
var lockModes = new Dictionary<string, LockMode>();
124+
var canAddCollectionsToCache = true;
124125
foreach (KeyValuePair<string, LockMode> me in rootCriteria.LockModes)
125126
{
126127
ICriteria subcriteria = GetAliasedCriteria(me.Key);
@@ -134,6 +135,9 @@ public QueryParameters GetQueryParameters()
134135
{
135136
lockModes[GetSQLAlias(subcriteria)] = lm;
136137
}
138+
139+
if (subcriteria.HasRestrictions && subcriteria.JoinType == JoinType.LeftOuterJoin)
140+
canAddCollectionsToCache = false;
137141
}
138142

139143
IDictionary<string, TypedValue> queryNamedParameters = CollectedParameters.ToDictionary(np => np.Name, np => new TypedValue(np.Type, np.Value, EntityMode.Poco));
@@ -149,7 +153,8 @@ public QueryParameters GetQueryParameters()
149153
rootCriteria.CacheRegion,
150154
rootCriteria.Comment,
151155
rootCriteria.LookupByNaturalKey,
152-
rootCriteria.ResultTransformer);
156+
rootCriteria.ResultTransformer,
157+
canAddCollectionsToCache);
153158
}
154159

155160
public SqlString GetGroupBy()

src/NHibernate/Loader/Loader.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ protected object LoadSingleRow(IDataReader resultSet, ISessionImplementor sessio
299299
queryParameters.NamedParameters);
300300
}
301301

302-
InitializeEntitiesAndCollections(hydratedObjects, resultSet, session, queryParameters.IsReadOnly(session));
302+
InitializeEntitiesAndCollections(hydratedObjects, resultSet, session, queryParameters.IsReadOnly(session), queryParameters.CanAddCollectionsToCache);
303303
session.PersistenceContext.InitializeNonLazyCollections();
304304
return result;
305305
}
@@ -493,7 +493,7 @@ private IList DoQuery(ISessionImplementor session, QueryParameters queryParamete
493493
session.Batcher.CloseCommand(st, rs);
494494
}
495495

496-
InitializeEntitiesAndCollections(hydratedObjects, rs, session, queryParameters.IsReadOnly(session));
496+
InitializeEntitiesAndCollections(hydratedObjects, rs, session, queryParameters.IsReadOnly(session), queryParameters.CanAddCollectionsToCache);
497497

498498
if (createSubselects)
499499
{
@@ -575,7 +575,7 @@ private IEnumerable<SubselectFetch> CreateSubselects(IList<EntityKey[]> keys, Qu
575575
}
576576
}
577577

578-
internal void InitializeEntitiesAndCollections(IList hydratedObjects, object resultSetId, ISessionImplementor session, bool readOnly)
578+
internal void InitializeEntitiesAndCollections(IList hydratedObjects, object resultSetId, ISessionImplementor session, bool readOnly, bool canAddCollectionsToCache)
579579
{
580580
ICollectionPersister[] collectionPersisters = CollectionPersisters;
581581
if (collectionPersisters != null)
@@ -589,7 +589,7 @@ internal void InitializeEntitiesAndCollections(IList hydratedObjects, object res
589589
//during loading
590590
//TODO: or we could do this polymorphically, and have two
591591
// different operations implemented differently for arrays
592-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
592+
EndCollectionLoad(resultSetId, session, collectionPersisters[i], canAddCollectionsToCache);
593593
}
594594
}
595595
}
@@ -633,17 +633,17 @@ internal void InitializeEntitiesAndCollections(IList hydratedObjects, object res
633633
//the entities, since we might call hashCode() on the elements
634634
//TODO: or we could do this polymorphically, and have two
635635
// different operations implemented differently for arrays
636-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
636+
EndCollectionLoad(resultSetId, session, collectionPersisters[i], canAddCollectionsToCache);
637637
}
638638
}
639639
}
640640
}
641641

642-
private static void EndCollectionLoad(object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister)
642+
private static void EndCollectionLoad(object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister, bool canAddCollectionsToCache)
643643
{
644644
//this is a query and we are loading multiple instances of the same collection role
645645
session.PersistenceContext.LoadContexts.GetCollectionLoadContext((IDataReader)resultSetId).EndLoadingCollections(
646-
collectionPersister);
646+
collectionPersister, canAddCollectionsToCache);
647647
}
648648

649649

0 commit comments

Comments
 (0)