From 6a65a2da01a64037acde4bf7afed8c033b06fdb4 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Sun, 2 Jul 2023 14:28:56 +0300 Subject: [PATCH 1/3] test case --- .../GhostProperty/GhostPropertyFixture.cs | 49 +++++++++++++++++++ .../GhostProperty/Mappings.hbm.xml | 1 + src/NHibernate.Test/GhostProperty/Order.cs | 3 +- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs b/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs index 13a3c6e0e7b..70e1e21613e 100644 --- a/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs +++ b/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs @@ -260,5 +260,54 @@ public void WillFetchJoinInSingleHqlQuery() Assert.DoesNotThrow(() => { var x = order.Payment; }); } + + [Test(Description = "GH-1267(NH-3047)")] + public void WillFetchJoinInAdditionalHqlQuery() + { + Order order = null; + + // load the order... + ISession s = OpenSession(); + order = s.CreateQuery("from Order o where o.Id = 1").List()[0]; + s.Disconnect(); + + Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; }); + + s.Reconnect(); + // ... then join-fetch the related payment + s.CreateQuery("from Order o left join fetch o.Payment where o.Id = 1").List(); + s.Close(); + + Assert.DoesNotThrow(() => { var x = order.Payment; }); + Assert.That(order.Payment.Type, Is.EqualTo("WT")); + } + + [Test(Description = "GH-1267(NH-3047)")] + public void WillFetchJoinWithCriteria() + { + Order order = null; + + // load the order... + ISession s = OpenSession(); + + var query = s.CreateCriteria(); + query.Add(Criterion.Restrictions.Eq("Id", 1)); + order = query.List()[0]; + s.Disconnect(); + + Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; }); + + s.Reconnect(); + + // ... then join-fetch the related payment + var query2 = s.CreateCriteria(); + query2.Add(Criterion.Restrictions.Eq("Id", 1)); + query2.Fetch(SelectMode.Fetch, "Payment"); + query2.List(); + s.Close(); + + Assert.DoesNotThrow(() => { var x = order.Payment; }); + Assert.That(order.Payment.Type, Is.EqualTo("WT")); + } } } diff --git a/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml b/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml index 2594f4c5afa..6790652371b 100644 --- a/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml +++ b/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml @@ -19,6 +19,7 @@ + diff --git a/src/NHibernate.Test/GhostProperty/Order.cs b/src/NHibernate.Test/GhostProperty/Order.cs index a0ef5e9a01b..99c0465c1cc 100644 --- a/src/NHibernate.Test/GhostProperty/Order.cs +++ b/src/NHibernate.Test/GhostProperty/Order.cs @@ -18,8 +18,9 @@ public virtual Payment Payment public abstract class Payment { public virtual int Id { get; set; } + public virtual string Type { get; set; } } public class WireTransfer : Payment{} public class CreditCard : Payment { } -} \ No newline at end of file +} From faea3b7ef331275c10dbd8b389de67a60d9e92bf Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Sun, 2 Jul 2023 14:34:30 +0300 Subject: [PATCH 2/3] Fix --- .../Intercept/AbstractFieldInterceptor.cs | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/NHibernate/Intercept/AbstractFieldInterceptor.cs b/src/NHibernate/Intercept/AbstractFieldInterceptor.cs index 87ede553e0a..898805360d9 100644 --- a/src/NHibernate/Intercept/AbstractFieldInterceptor.cs +++ b/src/NHibernate/Intercept/AbstractFieldInterceptor.cs @@ -128,39 +128,43 @@ public object Intercept(object target, string fieldName, object value, bool sett return InvokeImplementation; } - if (IsInitializedField(fieldName)) + if (IsUninitializedProperty(fieldName)) { - return value; - } + if (session == null) + { + throw new LazyInitializationException(EntityName, null, string.Format("entity with lazy properties is not associated with a session. entity-name:'{0}' property:'{1}'", EntityName, fieldName)); + } + if (!session.IsOpen || !session.IsConnected) + { + throw new LazyInitializationException(EntityName, null, string.Format("session is not connected. entity-name:'{0}' property:'{1}'", EntityName, fieldName)); + } - if (session == null) - { - throw new LazyInitializationException(EntityName, null, string.Format("entity with lazy properties is not associated with a session. entity-name:'{0}' property:'{1}'", EntityName, fieldName)); - } - if (!session.IsOpen || !session.IsConnected) - { - throw new LazyInitializationException(EntityName, null, string.Format("session is not connected. entity-name:'{0}' property:'{1}'", EntityName, fieldName)); + return InitializeField(fieldName, target); } - if (IsUninitializedProperty(fieldName)) + if (!IsUninitializedAssociation(fieldName)) { - return InitializeField(fieldName, target); + return value; } - if (value.IsProxy() && IsUninitializedAssociation(fieldName)) + if (value is INHibernateProxy nhproxy) { - var nhproxy = value as INHibernateProxy; value = InitializeOrGetAssociation(nhproxy, fieldName); - // Set the property value in order to be accessible when the session is closed - var persister = session.Factory.GetEntityPersister(entityName); - persister.SetPropertyValue( - target, - persister.EntityMetamodel.BytecodeEnhancementMetadata.UnwrapProxyPropertiesMetadata.GetUnwrapProxyPropertyIndex(fieldName), - value); + if (session?.Factory.IsClosed == false) + { + // Set the property value in order to be accessible when the session is closed + var persister = session.Factory.GetEntityPersister(entityName); + persister.SetPropertyValue( + target, + persister.EntityMetamodel.GetPropertyIndex(fieldName), + value); + } return value; } - return InvokeImplementation; + + loadedUnwrapProxyFieldNames.Add(fieldName); + return value; } private bool IsUninitializedAssociation(string fieldName) @@ -181,7 +185,7 @@ private object InitializeOrGetAssociation(INHibernateProxy value, string fieldNa value.HibernateLazyInitializer.Unwrap = true; // means that future Load/Get from the session will get the implementation loadedUnwrapProxyFieldNames.Add(fieldName); } - return value.HibernateLazyInitializer.GetImplementation(session); + return value.HibernateLazyInitializer.GetImplementation(); } private object InitializeField(string fieldName, object target) From afdf773e7403be9537e3bb6efd2df420dc4a9b05 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 2 Jul 2023 14:04:11 +0000 Subject: [PATCH 3/3] Generate async files --- .../GhostProperty/GhostPropertyFixture.cs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/NHibernate.Test/Async/GhostProperty/GhostPropertyFixture.cs b/src/NHibernate.Test/Async/GhostProperty/GhostPropertyFixture.cs index 12ab309a529..281ed163c32 100644 --- a/src/NHibernate.Test/Async/GhostProperty/GhostPropertyFixture.cs +++ b/src/NHibernate.Test/Async/GhostProperty/GhostPropertyFixture.cs @@ -253,5 +253,54 @@ public async Task WillFetchJoinInSingleHqlQueryAsync() Assert.DoesNotThrow(() => { var x = order.Payment; }); } + + [Test(Description = "GH-1267(NH-3047)")] + public async Task WillFetchJoinInAdditionalHqlQueryAsync() + { + Order order = null; + + // load the order... + ISession s = OpenSession(); + order = (await (s.CreateQuery("from Order o where o.Id = 1").ListAsync()))[0]; + s.Disconnect(); + + Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; }); + + s.Reconnect(); + // ... then join-fetch the related payment + await (s.CreateQuery("from Order o left join fetch o.Payment where o.Id = 1").ListAsync()); + s.Close(); + + Assert.DoesNotThrow(() => { var x = order.Payment; }); + Assert.That(order.Payment.Type, Is.EqualTo("WT")); + } + + [Test(Description = "GH-1267(NH-3047)")] + public async Task WillFetchJoinWithCriteriaAsync() + { + Order order = null; + + // load the order... + ISession s = OpenSession(); + + var query = s.CreateCriteria(); + query.Add(Criterion.Restrictions.Eq("Id", 1)); + order = (await (query.ListAsync()))[0]; + s.Disconnect(); + + Assert.Throws(typeof(LazyInitializationException), () => { var y = order.Payment; }); + + s.Reconnect(); + + // ... then join-fetch the related payment + var query2 = s.CreateCriteria(); + query2.Add(Criterion.Restrictions.Eq("Id", 1)); + query2.Fetch(SelectMode.Fetch, "Payment"); + await (query2.ListAsync()); + s.Close(); + + Assert.DoesNotThrow(() => { var x = order.Payment; }); + Assert.That(order.Payment.Type, Is.EqualTo("WT")); + } } }