Skip to content

Commit 6c9ad0c

Browse files
David UvenmanRogerKratz
authored andcommitted
#53 Fix for NullReferenceException in lazy bidirectional many-to-one properties
1 parent 01dd447 commit 6c9ad0c

File tree

6 files changed

+137
-4
lines changed

6 files changed

+137
-4
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System.Linq;
12+
using NUnit.Framework;
13+
using SharpTestsEx;
14+
15+
namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
16+
{
17+
using System.Threading.Tasks;
18+
public partial class LazyPropertyBidirectionalTest : TestBase
19+
{
20+
21+
[Test]
22+
public async Task SavePersonProxyForFieldInterceptorAsync()
23+
{
24+
long carId;
25+
using (var tx = Session.BeginTransaction())
26+
{
27+
var pers = Session.Query<Person>().Single(x => x.Id == id_pers1);
28+
var car = new Car
29+
{
30+
Owner = pers
31+
};
32+
pers.Cars.Add(car);
33+
carId = (long) await (Session.SaveAsync(car)).ConfigureAwait(false);
34+
await (tx.CommitAsync()).ConfigureAwait(false);
35+
}
36+
37+
(await (AuditReader().FindAsync<Car>(carId, 2)).ConfigureAwait(false)).Owner.Name
38+
.Should().Be.EqualTo("Hernan");
39+
}
40+
}
41+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using NHibernate.Envers.Configuration.Attributes;
2+
3+
namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
4+
{
5+
[Audited]
6+
public class Car
7+
{
8+
public virtual long Id { get; set; }
9+
public virtual int Number { get; set; }
10+
public virtual Person Owner { get; set; }
11+
}
12+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Linq;
2+
using NUnit.Framework;
3+
using SharpTestsEx;
4+
5+
namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
6+
{
7+
public partial class LazyPropertyBidirectionalTest : TestBase
8+
{
9+
private long id_pers1;
10+
11+
public LazyPropertyBidirectionalTest(AuditStrategyForTest strategyType) : base(strategyType)
12+
{
13+
}
14+
15+
protected override void Initialize()
16+
{
17+
var pers1 = new Person {Name = "Hernan"};
18+
19+
using (var tx = Session.BeginTransaction())
20+
{
21+
id_pers1 = (long) Session.Save(pers1);
22+
tx.Commit();
23+
}
24+
}
25+
26+
[Test]
27+
public void SavePersonProxyForFieldInterceptor()
28+
{
29+
long carId;
30+
using (var tx = Session.BeginTransaction())
31+
{
32+
var pers = Session.Query<Person>().Single(x => x.Id == id_pers1);
33+
var car = new Car
34+
{
35+
Owner = pers
36+
};
37+
pers.Cars.Add(car);
38+
carId = (long) Session.Save(car);
39+
tx.Commit();
40+
}
41+
42+
AuditReader().Find<Car>(carId, 2).Owner.Name
43+
.Should().Be.EqualTo("Hernan");
44+
}
45+
}
46+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
2+
assembly="NHibernate.Envers.Tests"
3+
namespace="NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional">
4+
<class name="Person" table="DRIVERS">
5+
<id name="Id" column="ID_PERSON" type="long">
6+
<generator class="native"/>
7+
</id>
8+
<property name="Name" type="string" length="255"
9+
column="NAME" not-null="true" lazy="true"/>
10+
11+
<set name="Cars" inverse="true" cascade="none">
12+
<key column="person_id" />
13+
<one-to-many class="Car" />
14+
</set>
15+
</class>
16+
17+
<class name="Car">
18+
<id name="Id" column="ID_CAR" type="long">
19+
<generator class="native"/>
20+
</id>
21+
<property name="Number" type="int" not-null="true" column="numb"/>
22+
<many-to-one name="Owner" class="Person" column="person_id"/>
23+
</class>
24+
</hibernate-mapping>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using NHibernate.Envers.Configuration.Attributes;
2+
using System.Collections.Generic;
3+
4+
namespace NHibernate.Envers.Tests.NetSpecific.Integration.ManyToOne.LazyProperty.Bidirectional
5+
{
6+
[Audited]
7+
public class Person
8+
{
9+
public virtual long Id { get; set; }
10+
public virtual string Name { get; set; }
11+
public virtual ISet<Car> Cars { get; set; }
12+
}
13+
}

Src/NHibernate.Envers/Event/AuditEventListener.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,17 @@ private void addCollectionChangeWorkUnit(AuditProcess auditProcess, ISessionImpl
8181
{
8282
// relDesc.getToEntityName() doesn't always return the entity name of the value - in case
8383
// of subclasses, this will be root class, no the actual class. So it can't be used here.
84-
string toEntityName;
8584
object id;
8685

86+
var toEntityName = session.BestGuessEntityName(value);
8787
if (value is INHibernateProxy newValueAsProxy)
8888
{
89-
toEntityName = session.BestGuessEntityName(value);
9089
id = newValueAsProxy.HibernateLazyInitializer.Identifier;
9190
// We've got to initialize the object from the proxy to later read its state.
9291
value = Toolz.GetTargetFromProxy(session, newValueAsProxy);
9392
}
9493
else
9594
{
96-
toEntityName = session.GuessEntityName(value);
97-
9895
var idMapper = VerCfg.EntCfg[toEntityName].IdMapper;
9996
id = idMapper.MapToIdFromEntity(value);
10097
}

0 commit comments

Comments
 (0)