From 02694a17d1af45a02732157bfd815bb424701efc Mon Sep 17 00:00:00 2001 From: maca88 Date: Thu, 1 Apr 2021 23:36:05 +0200 Subject: [PATCH] Fix deserialization with initialized proxies in associations --- .../Async/NHSpecificTest/GH2673/Fixture.cs | 138 ++++++++++++++++++ .../NHSpecificTest/GH2673/Fixture.cs | 127 ++++++++++++++++ .../NHSpecificTest/GH2673/Mappings.hbm.xml | 22 +++ .../NHSpecificTest/GH2673/Resource.cs | 13 ++ .../NHSpecificTest/GH2673/Role.cs | 11 ++ src/NHibernate/Proxy/StaticProxyFactory.cs | 30 ++-- 6 files changed, 329 insertions(+), 12 deletions(-) create mode 100644 src/NHibernate.Test/Async/NHSpecificTest/GH2673/Fixture.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2673/Fixture.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2673/Mappings.hbm.xml create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2673/Resource.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2673/Role.cs diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH2673/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH2673/Fixture.cs new file mode 100644 index 00000000000..8d03891ef6d --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH2673/Fixture.cs @@ -0,0 +1,138 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by AsyncGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using NHibernate.Util; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH2673 +{ + using System.Threading.Tasks; + [TestFixture] + public class FixtureAsync : BugTestCase + { + private readonly BinaryFormatter _formatter; + + public FixtureAsync() + { + _formatter = new BinaryFormatter + { +#if !NETFX + SurrogateSelector = new SerializationHelper.SurrogateSelector() +#endif + }; + } + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var role1 = new Role + { + Name = "Role1", + Key = 11 + }; + var role2 = new Role + { + Name = "Role2", + Key = 22 + }; + var resource1 = new Resource + { + Key = 1, + Name = "Resource1", + ResourceRole = role1 + }; + var resource2 = new Resource + { + Key = 2, + Name = "Resource2", + ResourceRole = role2, + Manager = resource1 + }; + session.Save(role1); + session.Save(role2); + session.Save(resource1); + session.Save(resource2); + + transaction.Commit(); + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + session.CreateQuery("delete from Resource").ExecuteUpdate(); + session.CreateQuery("delete from Role").ExecuteUpdate(); + session.CreateQuery("delete from System.Object").ExecuteUpdate(); + + transaction.Commit(); + } + } + + [Test] + public async Task TestSerializationAsync() + { + using (var session = OpenSession()) + using (var t = session.BeginTransaction()) + { + var resource = await (session.GetAsync(2)); + await (session.GetAsync(1)); + + var serialized = Serialize(resource); + Deserialize(serialized); + + await (t.CommitAsync()); + } + } + + [Test] + public async Task TestSerialization2Async() + { + using (var session = OpenSession()) + using (var t = session.BeginTransaction()) + { + await (session.GetAsync(1)); + var resource = await (session.GetAsync(2)); + + var serialized = Serialize(resource); + Deserialize(serialized); + + await (t.CommitAsync()); + } + } + private byte[] Serialize(object value) + { + using (var stream = new MemoryStream()) + { + _formatter.Serialize(stream, value); + var result = new byte[stream.Length]; + stream.Position = 0; + stream.Read(result, 0, (int) stream.Length); + stream.Close(); + return result; + } + } + + private object Deserialize(byte[] state) + { + using (var stream = new MemoryStream()) + { + stream.Write(state, 0, state.Length); + stream.Position = 0; + return _formatter.Deserialize(stream); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2673/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH2673/Fixture.cs new file mode 100644 index 00000000000..ab3767ab4cd --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2673/Fixture.cs @@ -0,0 +1,127 @@ +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using NHibernate.Util; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH2673 +{ + [TestFixture] + public class Fixture : BugTestCase + { + private readonly BinaryFormatter _formatter; + + public Fixture() + { + _formatter = new BinaryFormatter + { +#if !NETFX + SurrogateSelector = new SerializationHelper.SurrogateSelector() +#endif + }; + } + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var role1 = new Role + { + Name = "Role1", + Key = 11 + }; + var role2 = new Role + { + Name = "Role2", + Key = 22 + }; + var resource1 = new Resource + { + Key = 1, + Name = "Resource1", + ResourceRole = role1 + }; + var resource2 = new Resource + { + Key = 2, + Name = "Resource2", + ResourceRole = role2, + Manager = resource1 + }; + session.Save(role1); + session.Save(role2); + session.Save(resource1); + session.Save(resource2); + + transaction.Commit(); + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + session.CreateQuery("delete from Resource").ExecuteUpdate(); + session.CreateQuery("delete from Role").ExecuteUpdate(); + session.CreateQuery("delete from System.Object").ExecuteUpdate(); + + transaction.Commit(); + } + } + + [Test] + public void TestSerialization() + { + using (var session = OpenSession()) + using (var t = session.BeginTransaction()) + { + var resource = session.Get(2); + session.Get(1); + + var serialized = Serialize(resource); + Deserialize(serialized); + + t.Commit(); + } + } + + [Test] + public void TestSerialization2() + { + using (var session = OpenSession()) + using (var t = session.BeginTransaction()) + { + session.Get(1); + var resource = session.Get(2); + + var serialized = Serialize(resource); + Deserialize(serialized); + + t.Commit(); + } + } + private byte[] Serialize(object value) + { + using (var stream = new MemoryStream()) + { + _formatter.Serialize(stream, value); + var result = new byte[stream.Length]; + stream.Position = 0; + stream.Read(result, 0, (int) stream.Length); + stream.Close(); + return result; + } + } + + private object Deserialize(byte[] state) + { + using (var stream = new MemoryStream()) + { + stream.Write(state, 0, state.Length); + stream.Position = 0; + return _formatter.Deserialize(stream); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2673/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH2673/Mappings.hbm.xml new file mode 100644 index 00000000000..2e45fdb85c2 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2673/Mappings.hbm.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NHibernate.Test/NHSpecificTest/GH2673/Resource.cs b/src/NHibernate.Test/NHSpecificTest/GH2673/Resource.cs new file mode 100644 index 00000000000..496c40d68d1 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2673/Resource.cs @@ -0,0 +1,13 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.GH2673 +{ + [Serializable] + public class Resource + { + public virtual int Key { get; set; } + public virtual Resource Manager { get; set; } + public virtual string Name { get; set; } + public virtual Role ResourceRole { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2673/Role.cs b/src/NHibernate.Test/NHSpecificTest/GH2673/Role.cs new file mode 100644 index 00000000000..0a52238de71 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2673/Role.cs @@ -0,0 +1,11 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.GH2673 +{ + [Serializable] + public class Role + { + public virtual string Name { get; set; } + public virtual int Key { get; set; } + } +} diff --git a/src/NHibernate/Proxy/StaticProxyFactory.cs b/src/NHibernate/Proxy/StaticProxyFactory.cs index fa324ea574a..fd1dc7d6698 100644 --- a/src/NHibernate/Proxy/StaticProxyFactory.cs +++ b/src/NHibernate/Proxy/StaticProxyFactory.cs @@ -18,17 +18,23 @@ private static readonly ConcurrentDictionary CreateProxyActivator(pke)); + var proxyActivator = Cache.GetOrAdd(_cacheEntry, CreateProxyActivator); return proxyActivator( new LiteLazyInitializer(EntityName, id, session, PersistentClass), - _proxyFactoryInfo); + new NHibernateProxyFactoryInfo( + EntityName, + PersistentClass, + Interfaces, + GetIdentifierMethod, + SetIdentifierMethod, + ComponentIdType, + IsClassProxy)); } catch (Exception ex) { @@ -48,14 +54,6 @@ public override void PostInstantiate( { base.PostInstantiate(entityName, persistentClass, interfaces, getIdentifierMethod, setIdentifierMethod, componentIdType, isClassProxy); - _proxyFactoryInfo = new NHibernateProxyFactoryInfo( - EntityName, - PersistentClass, - Interfaces, - GetIdentifierMethod, - SetIdentifierMethod, - ComponentIdType, - IsClassProxy); _cacheEntry = new ProxyCacheEntry(IsClassProxy ? PersistentClass : typeof(object), Interfaces); } @@ -79,7 +77,15 @@ public override object GetFieldInterceptionProxy(object instanceToWrap) public object GetFieldInterceptionProxy() { var proxyActivator = FieldInterceptorCache.GetOrAdd(PersistentClass, CreateFieldInterceptionProxyActivator); - return proxyActivator(_proxyFactoryInfo); + return proxyActivator( + new NHibernateProxyFactoryInfo( + EntityName, + PersistentClass, + Interfaces, + GetIdentifierMethod, + SetIdentifierMethod, + ComponentIdType, + IsClassProxy)); } private Func CreateFieldInterceptionProxyActivator(System.Type baseType)