Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for NullReferenceException in lazy bidirectional many-to-one properties #52

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System.Linq;
using NUnit.Framework;
using SharpTestsEx;

namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
{
using System.Threading.Tasks;
public partial class LazyPropertyBidirectionalTest : TestBase
{

[Test]
public async Task SavePersonProxyForFieldInterceptorAsync()
{
long carId;
using (var tx = Session.BeginTransaction())
{
var pers = Session.Query<Person>().Single(x => x.Id == id_pers1);
var car = new Car
{
Owner = pers
};
pers.Cars.Add(car);
carId = (long) await (Session.SaveAsync(car)).ConfigureAwait(false);
await (tx.CommitAsync()).ConfigureAwait(false);
}

(await (AuditReader().FindAsync<Car>(carId, 2)).ConfigureAwait(false)).Owner.Name
.Should().Be.EqualTo("Hernan");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using NHibernate.Envers.Configuration.Attributes;

namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
{
[Audited]
public class Car
{
public virtual long Id { get; set; }
public virtual int Number { get; set; }
public virtual Person Owner { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Linq;
using NUnit.Framework;
using SharpTestsEx;

namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
{
public partial class LazyPropertyBidirectionalTest : TestBase
{
private long id_pers1;

public LazyPropertyBidirectionalTest(AuditStrategyForTest strategyType) : base(strategyType)
{
}

protected override void Initialize()
{
var pers1 = new Person {Name = "Hernan"};

using (var tx = Session.BeginTransaction())
{
id_pers1 = (long) Session.Save(pers1);
tx.Commit();
}
}

[Test]
public void SavePersonProxyForFieldInterceptor()
{
long carId;
using (var tx = Session.BeginTransaction())
{
var pers = Session.Query<Person>().Single(x => x.Id == id_pers1);
var car = new Car
{
Owner = pers
};
pers.Cars.Add(car);
carId = (long) Session.Save(car);
tx.Commit();
}

AuditReader().Find<Car>(carId, 2).Owner.Name
.Should().Be.EqualTo("Hernan");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernate.Envers.Tests"
namespace="NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional">
<class name="Person" table="DRIVERS">
<id name="Id" column="ID_PERSON" type="long">
<generator class="native"/>
</id>
<property name="Name" type="string" length="255"
column="NAME" not-null="true" lazy="true"/>

<set name="Cars" inverse="true" cascade="none">
<key column="person_id" />
<one-to-many class="Car" />
</set>
</class>

<class name="Car">
<id name="Id" column="ID_CAR" type="long">
<generator class="native"/>
</id>
<property name="Number" type="int" not-null="true" column="numb"/>
<many-to-one name="Owner" class="Person" column="person_id"/>
</class>
</hibernate-mapping>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using NHibernate.Envers.Configuration.Attributes;
using System.Collections.Generic;

namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
{
[Audited]
public class Person
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<Car> Cars { get; set; }
}
}
17 changes: 7 additions & 10 deletions Src/NHibernate.Envers/Event/AuditEventListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,17 @@ private void addCollectionChangeWorkUnit(AuditProcess auditProcess, ISessionImpl
{
// relDesc.getToEntityName() doesn't always return the entity name of the value - in case
// of subclasses, this will be root class, no the actual class. So it can't be used here.
string toEntityName;
object id;

var toEntityName = session.BestGuessEntityName(value);
if (value is INHibernateProxy newValueAsProxy)
{
toEntityName = session.BestGuessEntityName(value);
id = newValueAsProxy.HibernateLazyInitializer.Identifier;
// We've got to initialize the object from the proxy to later read its state.
value = Toolz.GetTargetFromProxy(session, newValueAsProxy);
}
else
{
toEntityName = session.GuessEntityName(value);

var idMapper = VerCfg.EntCfg[toEntityName].IdMapper;
id = idMapper.MapToIdFromEntity(value);
}
Expand Down Expand Up @@ -223,10 +220,10 @@ private void generateBidirectionalCollectionChangeWorkUnits(AuditProcess auditPr
var toPropertyName = toPropertyNames.First();

auditProcess.AddWorkUnit(new CollectionChangeWorkUnit(evt.Session,
evt.Session.BestGuessEntityName(relatedObj),
evt.Session.BestGuessEntityName(relatedObj),
toPropertyName,
VerCfg,
relatedId,
VerCfg,
relatedId,
relatedObj));
}
}
Expand Down Expand Up @@ -299,7 +296,7 @@ private void onCollectionAction(AbstractCollectionEvent evt,
}
else
{
var workUnit = new PersistentCollectionChangeWorkUnit(evt.Session, entityName, VerCfg, newColl,
var workUnit = new PersistentCollectionChangeWorkUnit(evt.Session, entityName, VerCfg, newColl,
collectionEntry, oldColl, evt.AffectedOwnerIdOrNull,
referencingPropertyName);
verSync.AddWorkUnit(workUnit);
Expand Down Expand Up @@ -400,7 +397,7 @@ public virtual void Initialize(Cfg.Configuration cfg)

private static void checkIfTransactionInProgress(ISessionImplementor session)
{
if (!session.TransactionInProgress && session.TransactionContext==null)
if (!session.TransactionInProgress && session.TransactionContext == null)
{
// Historical data would not be flushed to audit tables if outside of active transaction
// (AuditProcess#doBeforeTransactionCompletion(SessionImplementor) not executed).
Expand All @@ -412,7 +409,7 @@ private bool shouldGenerateRevision(AbstractCollectionEvent evt)
{
var entityName = evt.GetAffectedOwnerEntityName();
return VerCfg.GlobalCfg.GenerateRevisionsForCollections
&& VerCfg.EntCfg.IsVersioned(entityName);
&& VerCfg.EntCfg.IsVersioned(entityName);
}

private static object initializeCollection(AbstractCollectionEvent evt)
Expand Down
Loading