Skip to content

Commit 7d53824

Browse files
itmaginationhazzik
authored andcommitted
Fix using Criteria and QuerOver for NH-3848
1 parent d00151f commit 7d53824

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
{
@@ -189,7 +190,7 @@ public void EndLoadingCollections(ICollectionPersister persister)
189190
}
190191
localLoadingCollectionKeys.ExceptWith(toRemove);
191192

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

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

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

227228
if (log.IsDebugEnabled())
@@ -230,7 +231,7 @@ private void EndLoadingCollections(ICollectionPersister persister, IList<Loading
230231
}
231232
}
232233

233-
private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersister persister)
234+
private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersister persister, bool canAddCollectionsToCache)
234235
{
235236
if (log.IsDebugEnabled())
236237
{
@@ -264,7 +265,7 @@ private void EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersist
264265
ce.PostInitialize(lce.Collection, persistenceContext);
265266
}
266267

267-
bool addToCache = hasNoQueuedAdds && persister.HasCache &&
268+
bool addToCache = canAddCollectionsToCache && hasNoQueuedAdds && persister.HasCache &&
268269
session.CacheMode.HasFlag(CacheMode.Put) && !ce.IsDoremove; // and this is not a forced initialization during flush
269270

270271
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, Array.Empty<object>(), 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 ?? Array.Empty<IType>();
6565
PositionalParameterValues = positionalParameterValues ?? Array.Empty<object>();
@@ -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
@@ -687,6 +687,7 @@ public sealed partial class Subcriteria : ICriteria, ISupportSelectModeCriteria
687687
private LockMode lockMode;
688688
private readonly JoinType joinType;
689689
private ICriterion withClause;
690+
private bool hasRestrictions;
690691

691692
internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string alias, JoinType joinType, ICriterion withClause, string joinEntityName = null)
692693
{
@@ -697,6 +698,7 @@ internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string al
697698
this.joinType = joinType;
698699
this.withClause = withClause;
699700
JoinEntityName = joinEntityName;
701+
hasRestrictions = withClause != null;
700702

701703
root.subcriteriaList.Add(this);
702704

@@ -730,6 +732,11 @@ public string Path
730732
get { return path; }
731733
}
732734

735+
public bool HasRestrictions
736+
{
737+
get { return hasRestrictions; }
738+
}
739+
733740
public ICriteria Parent
734741
{
735742
get { return parent; }
@@ -769,6 +776,7 @@ public ICriteria SetLockMode(LockMode lockMode)
769776

770777
public ICriteria Add(ICriterion expression)
771778
{
779+
hasRestrictions = true;
772780
root.Add(this, expression);
773781
return this;
774782
}

src/NHibernate/Impl/MultiCriteriaImpl.cs

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

272272
if (createSubselects[i])
273273
{

src/NHibernate/Impl/MultiQueryImpl.cs

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

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

611611
if (createSubselects[i])
612612
{

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

173178
public SqlString GetGroupBy()

src/NHibernate/Loader/Loader.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ protected object LoadSingleRow(DbDataReader resultSet, ISessionImplementor sessi
310310
queryParameters.NamedParameters);
311311
}
312312

313-
InitializeEntitiesAndCollections(hydratedObjects, resultSet, session, queryParameters.IsReadOnly(session));
313+
InitializeEntitiesAndCollections(hydratedObjects, resultSet, session, queryParameters.IsReadOnly(session), queryParameters.CanAddCollectionsToCache);
314314
session.PersistenceContext.InitializeNonLazyCollections();
315315
return result;
316316
}
@@ -512,7 +512,7 @@ private IList DoQuery(ISessionImplementor session, QueryParameters queryParamete
512512
session.Batcher.CloseCommand(st, rs);
513513
}
514514

515-
InitializeEntitiesAndCollections(hydratedObjects, rs, session, queryParameters.IsReadOnly(session));
515+
InitializeEntitiesAndCollections(hydratedObjects, rs, session, queryParameters.IsReadOnly(session), queryParameters.CanAddCollectionsToCache);
516516

517517
if (createSubselects)
518518
{
@@ -594,7 +594,7 @@ private IEnumerable<SubselectFetch> CreateSubselects(IList<EntityKey[]> keys, Qu
594594
}
595595
}
596596

597-
internal void InitializeEntitiesAndCollections(IList hydratedObjects, object resultSetId, ISessionImplementor session, bool readOnly)
597+
internal void InitializeEntitiesAndCollections(IList hydratedObjects, object resultSetId, ISessionImplementor session, bool readOnly, bool canAddCollectionsToCache)
598598
{
599599
ICollectionPersister[] collectionPersisters = CollectionPersisters;
600600
if (collectionPersisters != null)
@@ -608,7 +608,7 @@ internal void InitializeEntitiesAndCollections(IList hydratedObjects, object res
608608
//during loading
609609
//TODO: or we could do this polymorphically, and have two
610610
// different operations implemented differently for arrays
611-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
611+
EndCollectionLoad(resultSetId, session, collectionPersisters[i], canAddCollectionsToCache);
612612
}
613613
}
614614
}
@@ -652,17 +652,17 @@ internal void InitializeEntitiesAndCollections(IList hydratedObjects, object res
652652
//the entities, since we might call hashCode() on the elements
653653
//TODO: or we could do this polymorphically, and have two
654654
// different operations implemented differently for arrays
655-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
655+
EndCollectionLoad(resultSetId, session, collectionPersisters[i], canAddCollectionsToCache);
656656
}
657657
}
658658
}
659659
}
660660

661-
private static void EndCollectionLoad(object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister)
661+
private static void EndCollectionLoad(object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister, bool canAddCollectionsToCache)
662662
{
663663
//this is a query and we are loading multiple instances of the same collection role
664664
session.PersistenceContext.LoadContexts.GetCollectionLoadContext((DbDataReader)resultSetId).EndLoadingCollections(
665-
collectionPersister);
665+
collectionPersister, canAddCollectionsToCache);
666666
}
667667

668668

0 commit comments

Comments
 (0)