Skip to content

Commit 770b365

Browse files
authored
Fix getting of initialized proxies for no-proxy associations outside of session scope (#3347)
Fixes #1267
1 parent a390e6d commit 770b365

File tree

5 files changed

+127
-23
lines changed

5 files changed

+127
-23
lines changed

src/NHibernate.Test/Async/GhostProperty/GhostPropertyFixture.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,5 +253,54 @@ public async Task WillFetchJoinInSingleHqlQueryAsync()
253253

254254
Assert.DoesNotThrow(() => { var x = order.Payment; });
255255
}
256+
257+
[Test(Description = "GH-1267(NH-3047)")]
258+
public async Task WillFetchJoinInAdditionalHqlQueryAsync()
259+
{
260+
Order order = null;
261+
262+
// load the order...
263+
ISession s = OpenSession();
264+
order = (await (s.CreateQuery("from Order o where o.Id = 1").ListAsync<Order>()))[0];
265+
s.Disconnect();
266+
267+
Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; });
268+
269+
s.Reconnect();
270+
// ... then join-fetch the related payment
271+
await (s.CreateQuery("from Order o left join fetch o.Payment where o.Id = 1").ListAsync<Order>());
272+
s.Close();
273+
274+
Assert.DoesNotThrow(() => { var x = order.Payment; });
275+
Assert.That(order.Payment.Type, Is.EqualTo("WT"));
276+
}
277+
278+
[Test(Description = "GH-1267(NH-3047)")]
279+
public async Task WillFetchJoinWithCriteriaAsync()
280+
{
281+
Order order = null;
282+
283+
// load the order...
284+
ISession s = OpenSession();
285+
286+
var query = s.CreateCriteria<Order>();
287+
query.Add(Criterion.Restrictions.Eq("Id", 1));
288+
order = (await (query.ListAsync<Order>()))[0];
289+
s.Disconnect();
290+
291+
Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; });
292+
293+
s.Reconnect();
294+
295+
// ... then join-fetch the related payment
296+
var query2 = s.CreateCriteria<Order>();
297+
query2.Add(Criterion.Restrictions.Eq("Id", 1));
298+
query2.Fetch(SelectMode.Fetch, "Payment");
299+
await (query2.ListAsync());
300+
s.Close();
301+
302+
Assert.DoesNotThrow(() => { var x = order.Payment; });
303+
Assert.That(order.Payment.Type, Is.EqualTo("WT"));
304+
}
256305
}
257306
}

src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,5 +260,54 @@ public void WillFetchJoinInSingleHqlQuery()
260260

261261
Assert.DoesNotThrow(() => { var x = order.Payment; });
262262
}
263+
264+
[Test(Description = "GH-1267(NH-3047)")]
265+
public void WillFetchJoinInAdditionalHqlQuery()
266+
{
267+
Order order = null;
268+
269+
// load the order...
270+
ISession s = OpenSession();
271+
order = s.CreateQuery("from Order o where o.Id = 1").List<Order>()[0];
272+
s.Disconnect();
273+
274+
Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; });
275+
276+
s.Reconnect();
277+
// ... then join-fetch the related payment
278+
s.CreateQuery("from Order o left join fetch o.Payment where o.Id = 1").List<Order>();
279+
s.Close();
280+
281+
Assert.DoesNotThrow(() => { var x = order.Payment; });
282+
Assert.That(order.Payment.Type, Is.EqualTo("WT"));
283+
}
284+
285+
[Test(Description = "GH-1267(NH-3047)")]
286+
public void WillFetchJoinWithCriteria()
287+
{
288+
Order order = null;
289+
290+
// load the order...
291+
ISession s = OpenSession();
292+
293+
var query = s.CreateCriteria<Order>();
294+
query.Add(Criterion.Restrictions.Eq("Id", 1));
295+
order = query.List<Order>()[0];
296+
s.Disconnect();
297+
298+
Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; });
299+
300+
s.Reconnect();
301+
302+
// ... then join-fetch the related payment
303+
var query2 = s.CreateCriteria<Order>();
304+
query2.Add(Criterion.Restrictions.Eq("Id", 1));
305+
query2.Fetch(SelectMode.Fetch, "Payment");
306+
query2.List();
307+
s.Close();
308+
309+
Assert.DoesNotThrow(() => { var x = order.Payment; });
310+
Assert.That(order.Payment.Type, Is.EqualTo("WT"));
311+
}
263312
}
264313
}

src/NHibernate.Test/GhostProperty/Mappings.hbm.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<generator class="assigned" />
2020
</id>
2121
<discriminator column="Type" type="System.String"/>
22+
<property name="Type" column="Type" insert="false" update="false" />
2223
<subclass name="WireTransfer" discriminator-value="WT">
2324

2425
</subclass>

src/NHibernate.Test/GhostProperty/Order.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ public virtual Payment Payment
1818
public abstract class Payment
1919
{
2020
public virtual int Id { get; set; }
21+
public virtual string Type { get; set; }
2122
}
2223

2324
public class WireTransfer : Payment{}
2425
public class CreditCard : Payment { }
25-
}
26+
}

src/NHibernate/Intercept/AbstractFieldInterceptor.cs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -128,39 +128,43 @@ public object Intercept(object target, string fieldName, object value, bool sett
128128
return InvokeImplementation;
129129
}
130130

131-
if (IsInitializedField(fieldName))
131+
if (IsUninitializedProperty(fieldName))
132132
{
133-
return value;
134-
}
133+
if (session == null)
134+
{
135+
throw new LazyInitializationException(EntityName, null, string.Format("entity with lazy properties is not associated with a session. entity-name:'{0}' property:'{1}'", EntityName, fieldName));
136+
}
137+
if (!session.IsOpen || !session.IsConnected)
138+
{
139+
throw new LazyInitializationException(EntityName, null, string.Format("session is not connected. entity-name:'{0}' property:'{1}'", EntityName, fieldName));
140+
}
135141

136-
if (session == null)
137-
{
138-
throw new LazyInitializationException(EntityName, null, string.Format("entity with lazy properties is not associated with a session. entity-name:'{0}' property:'{1}'", EntityName, fieldName));
139-
}
140-
if (!session.IsOpen || !session.IsConnected)
141-
{
142-
throw new LazyInitializationException(EntityName, null, string.Format("session is not connected. entity-name:'{0}' property:'{1}'", EntityName, fieldName));
142+
return InitializeField(fieldName, target);
143143
}
144144

145-
if (IsUninitializedProperty(fieldName))
145+
if (!IsUninitializedAssociation(fieldName))
146146
{
147-
return InitializeField(fieldName, target);
147+
return value;
148148
}
149149

150-
if (value.IsProxy() && IsUninitializedAssociation(fieldName))
150+
if (value is INHibernateProxy nhproxy)
151151
{
152-
var nhproxy = value as INHibernateProxy;
153152
value = InitializeOrGetAssociation(nhproxy, fieldName);
154-
// Set the property value in order to be accessible when the session is closed
155-
var persister = session.Factory.GetEntityPersister(entityName);
156-
persister.SetPropertyValue(
157-
target,
158-
persister.EntityMetamodel.BytecodeEnhancementMetadata.UnwrapProxyPropertiesMetadata.GetUnwrapProxyPropertyIndex(fieldName),
159-
value);
153+
if (session?.Factory.IsClosed == false)
154+
{
155+
// Set the property value in order to be accessible when the session is closed
156+
var persister = session.Factory.GetEntityPersister(entityName);
157+
persister.SetPropertyValue(
158+
target,
159+
persister.EntityMetamodel.GetPropertyIndex(fieldName),
160+
value);
161+
}
160162

161163
return value;
162164
}
163-
return InvokeImplementation;
165+
166+
loadedUnwrapProxyFieldNames.Add(fieldName);
167+
return value;
164168
}
165169

166170
private bool IsUninitializedAssociation(string fieldName)
@@ -181,7 +185,7 @@ private object InitializeOrGetAssociation(INHibernateProxy value, string fieldNa
181185
value.HibernateLazyInitializer.Unwrap = true; // means that future Load/Get from the session will get the implementation
182186
loadedUnwrapProxyFieldNames.Add(fieldName);
183187
}
184-
return value.HibernateLazyInitializer.GetImplementation(session);
188+
return value.HibernateLazyInitializer.GetImplementation();
185189
}
186190

187191
private object InitializeField(string fieldName, object target)

0 commit comments

Comments
 (0)