diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH2508/AuditEventListener.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH2508/AuditEventListener.cs new file mode 100644 index 00000000000..3c2aaac0566 --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH2508/AuditEventListener.cs @@ -0,0 +1,46 @@ +//------------------------------------------------------------------------------ +// +// 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; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NHibernate.Cfg; +using NHibernate.Event; +using NHibernate.Persister.Entity; + +namespace NHibernate.Test.NHSpecificTest.GH2508 +{ + public partial class AuditEventListener : IPreCollectionUpdateEventListener + { + public Task OnPreUpdateCollectionAsync(PreCollectionUpdateEvent @event, CancellationToken cancellationToken) + { + try + { + var ownerEntity = @event.AffectedOwnerOrNull; + var collectionEntry = @event.Session.PersistenceContext.GetCollectionEntry(@event.Collection); + if (!collectionEntry.LoadedPersister.IsInverse) + return Task.CompletedTask; + + var abstractCollectionPersister = collectionEntry.LoadedPersister as Persister.Collection.AbstractCollectionPersister; + if (abstractCollectionPersister == null) + return Task.CompletedTask; + + var ownerEntityPersister = abstractCollectionPersister.OwnerEntityPersister; + ownerEntityPersister.GetPropertyValues(ownerEntity); + return Task.CompletedTask; + } + catch (Exception ex) + { + return Task.FromException(ex); + } + } + } +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH2508/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH2508/Fixture.cs new file mode 100644 index 00000000000..2dd46752b97 --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH2508/Fixture.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// 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.Linq; +using NHibernate.Cfg; +using NUnit.Framework; +using NHibernate.Linq; + +namespace NHibernate.Test.NHSpecificTest.GH2508 +{ + using System.Threading.Tasks; + [TestFixture] + public class FixtureAsync : BugTestCase + { + protected override void Configure(Configuration configuration) + { + var listeners = configuration.EventListeners; + listeners.PreCollectionUpdateEventListeners = + new[] {new AuditEventListener()} + .Concat(listeners.PreCollectionUpdateEventListeners) + .ToArray(); + } + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var e1 = new LoggerCase {Name = "Bob"}; + session.Save(e1); + + var e2 = new LoggerCase {Name = "Sally"}; + session.Save(e2); + + transaction.Commit(); + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + session.Delete("from System.Object"); + transaction.Commit(); + } + } + + [Test] + public async Task TestPreCollectionUpdateEventAsync() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var result = await ((from e in session.Query() + where e.Name == "Bob" + select e).FirstAsync()); + + result.Children.Add(new Child { Logger = result, Name = "child" }); + await (session.SaveOrUpdateAsync(result)); + await (transaction.CommitAsync()); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2508/AuditEventListener.cs b/src/NHibernate.Test/NHSpecificTest/GH2508/AuditEventListener.cs new file mode 100644 index 00000000000..8d6d2c6b291 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2508/AuditEventListener.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NHibernate.Cfg; +using NHibernate.Event; +using NHibernate.Persister.Entity; + +namespace NHibernate.Test.NHSpecificTest.GH2508 +{ + public partial class AuditEventListener : IPreCollectionUpdateEventListener + { + public void OnPreUpdateCollection(PreCollectionUpdateEvent @event) + { + var ownerEntity = @event.AffectedOwnerOrNull; + var collectionEntry = @event.Session.PersistenceContext.GetCollectionEntry(@event.Collection); + if (!collectionEntry.LoadedPersister.IsInverse) + return; + + var abstractCollectionPersister = collectionEntry.LoadedPersister as Persister.Collection.AbstractCollectionPersister; + if (abstractCollectionPersister == null) + return; + + var ownerEntityPersister = abstractCollectionPersister.OwnerEntityPersister; + ownerEntityPersister.GetPropertyValues(ownerEntity); + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2508/Child.cs b/src/NHibernate.Test/NHSpecificTest/GH2508/Child.cs new file mode 100644 index 00000000000..fd35585f90c --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2508/Child.cs @@ -0,0 +1,11 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.GH2508 +{ + public class Child + { + public virtual Guid Id { get; set; } + public virtual string Name { get; set; } + public virtual LoggerBase Logger { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2508/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH2508/Fixture.cs new file mode 100644 index 00000000000..b7ef5cef56f --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2508/Fixture.cs @@ -0,0 +1,60 @@ +using System.Linq; +using NHibernate.Cfg; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH2508 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void Configure(Configuration configuration) + { + var listeners = configuration.EventListeners; + listeners.PreCollectionUpdateEventListeners = + new[] {new AuditEventListener()} + .Concat(listeners.PreCollectionUpdateEventListeners) + .ToArray(); + } + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var e1 = new LoggerCase {Name = "Bob"}; + session.Save(e1); + + var e2 = new LoggerCase {Name = "Sally"}; + session.Save(e2); + + transaction.Commit(); + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + session.Delete("from System.Object"); + transaction.Commit(); + } + } + + [Test] + public void TestPreCollectionUpdateEvent() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var result = (from e in session.Query() + where e.Name == "Bob" + select e).First(); + + result.Children.Add(new Child { Logger = result, Name = "child" }); + session.SaveOrUpdate(result); + transaction.Commit(); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2508/LoggerBase.cs b/src/NHibernate.Test/NHSpecificTest/GH2508/LoggerBase.cs new file mode 100644 index 00000000000..c348790c73d --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2508/LoggerBase.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.GH2508 +{ + public abstract class LoggerBase + { + public LoggerBase() + { + Children = new List(); + } + + public virtual string Solution { get; set; } + + public virtual Guid Id { get; set; } + + public virtual string Name { get; set; } + + public virtual IList Children { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2508/LoggerCase.cs b/src/NHibernate.Test/NHSpecificTest/GH2508/LoggerCase.cs new file mode 100644 index 00000000000..fcc495c2505 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2508/LoggerCase.cs @@ -0,0 +1,7 @@ +namespace NHibernate.Test.NHSpecificTest.GH2508 +{ + public class LoggerCase : LoggerBase + { + public virtual string Description { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2508/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH2508/Mappings.hbm.xml new file mode 100644 index 00000000000..8b7a549cb20 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2508/Mappings.hbm.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataPocoImpl.cs b/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataPocoImpl.cs index 988e8767b63..e0adb041feb 100644 --- a/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataPocoImpl.cs +++ b/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataPocoImpl.cs @@ -132,7 +132,7 @@ public IFieldInterceptor InjectInterceptor(object entity, ISessionImplementor se return null; // Can happen when a saved entity is refreshed within the same session NH2860 } - if (entity.GetType().BaseType != _entityType) + if (!_entityType.IsInstanceOfType(entity)) { throw new ArgumentException( $"Passed entity instance [{entity}] is not of expected type [{EntityName}]"); @@ -170,7 +170,7 @@ public IFieldInterceptor ExtractInterceptor(object entity) return null; } - if (_entityType != interceptor.MappedClass) + if (!_entityType.IsAssignableFrom(interceptor.MappedClass)) { throw new ArgumentException( $"Passed entity instance [{entity}] is not of expected type [{EntityName}]");