Skip to content

Commit 3f3a095

Browse files
committed
NH-3505 - Check transience via unsaved id to eliminate need for hydrating entities to get version. Fixes lazy many-to-ones on versioned classes with stateless session updates.
1 parent 62578c6 commit 3f3a095

File tree

7 files changed

+165
-30
lines changed

7 files changed

+165
-30
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using NHibernate.Criterion;
5+
using NHibernate.Linq;
6+
using NHibernate.Linq.Functions;
7+
using NUnit.Framework;
8+
9+
namespace NHibernate.Test.NHSpecificTest.NH3505
10+
{
11+
[TestFixture]
12+
public class Fixture : BugTestCase
13+
{
14+
protected override void OnTearDown()
15+
{
16+
using (ISession s = sessions.OpenSession())
17+
{
18+
s.Delete("from Student");
19+
s.Delete("from Teacher");
20+
s.Flush();
21+
}
22+
}
23+
24+
[Test]
25+
public void StatelessSessionLazyUpdate()
26+
{
27+
var s = OpenSession();
28+
Guid studentId;
29+
Guid teacherId;
30+
try
31+
{
32+
var teacher = new Teacher {Name = "Wise Man"};
33+
s.Save(teacher);
34+
teacherId = teacher.Id;
35+
var student = new Student {Name = "Rebelious Teenager", Teacher = teacher};
36+
s.Save(student);
37+
studentId = student.Id;
38+
s.Flush();
39+
}
40+
finally
41+
{
42+
s.Close();
43+
}
44+
45+
var ss = Sfi.OpenStatelessSession();
46+
try
47+
{
48+
var trans = ss.BeginTransaction();
49+
try
50+
{
51+
var student = ss.Get<Student>(studentId);
52+
Assert.AreEqual(teacherId, student.Teacher.Id);
53+
Assert.AreEqual("Rebelious Teenager", student.Name);
54+
student.Name = "Young Protege";
55+
ss.Update(student);
56+
trans.Commit();
57+
}
58+
catch
59+
{
60+
trans.Rollback();
61+
throw;
62+
}
63+
}
64+
finally
65+
{
66+
ss.Close();
67+
}
68+
69+
s = OpenSession();
70+
try
71+
{
72+
var student = s.Get<Student>(studentId);
73+
Assert.AreEqual(teacherId, student.Teacher.Id);
74+
Assert.AreEqual("Young Protege", student.Name);
75+
}
76+
finally
77+
{
78+
s.Close();
79+
}
80+
}
81+
}
82+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH3505">
3+
<class name="Teacher" optimistic-lock="version">
4+
<id name="Id">
5+
<generator class="guid.comb" />
6+
</id>
7+
<version name="Version"/>
8+
<property name="Name"/>
9+
</class>
10+
<class name="Student">
11+
<id name="Id">
12+
<generator class="guid.comb" />
13+
</id>
14+
<property name="Name"/>
15+
<many-to-one name="Teacher"/>
16+
</class>
17+
</hibernate-mapping>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH3505
5+
{
6+
public class Student
7+
{
8+
public virtual Guid Id { get; set; }
9+
public virtual string Name { get; set; }
10+
public virtual Teacher Teacher { get; set; }
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH3505
5+
{
6+
public class Teacher
7+
{
8+
public virtual Guid Id { get; set; }
9+
public virtual int Version { get; set; }
10+
public virtual string Name { get; set; }
11+
}
12+
}

src/NHibernate.Test/NHSpecificTest/NH392/Fixture.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ public void UnsavedMinusOneNoNullReferenceException()
3333
tran.Rollback();
3434
}
3535
}
36-
}
36+
}
37+
38+
protected override void OnTearDown()
39+
{
40+
using (ISession s = sessions.OpenSession())
41+
{
42+
s.Delete("from UnsavedValueMinusOne");
43+
s.Flush();
44+
}
45+
}
3746
}
3847
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,9 @@
670670
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Domain.cs" />
671671
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Fixture.cs" />
672672
<Compile Include="Component\Basic\ComponentWithUniqueConstraintTests.cs" />
673+
<Compile Include="NHSpecificTest\NH3505\Student.cs" />
674+
<Compile Include="NHSpecificTest\NH3505\Teacher.cs" />
675+
<Compile Include="NHSpecificTest\NH3505\Fixture.cs" />
673676
<Compile Include="NHSpecificTest\NH2923\Models.cs" />
674677
<Compile Include="NHSpecificTest\NH2923\ExtraLazyFixture.cs" />
675678
<Compile Include="NHSpecificTest\NH3405\Fixture.cs" />
@@ -2895,6 +2898,7 @@
28952898
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
28962899
</ItemGroup>
28972900
<ItemGroup>
2901+
<EmbeddedResource Include="NHSpecificTest\NH3505\Mappings.hbm.xml" />
28982902
<EmbeddedResource Include="NHSpecificTest\NH3428\Mappings.hbm.xml" />
28992903
<EmbeddedResource Include="NHSpecificTest\NH3408\Mappings.hbm.xml" />
29002904
<EmbeddedResource Include="NHSpecificTest\NH2408\Mappings.hbm.xml" />

src/NHibernate/Persister/Entity/AbstractEntityPersister.cs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,35 +3686,34 @@ public virtual void AfterReassociate(object entity, ISessionImplementor session)
36863686
return true;
36873687
}
36883688

3689-
// check the version unsaved-value, if appropriate
3690-
if (IsVersioned)
3691-
{
3692-
object version = GetVersion(entity, session.EntityMode);
3693-
// let this take precedence if defined, since it works for
3694-
// assigned identifiers
3695-
bool? result = entityMetamodel.VersionProperty.UnsavedValue.IsUnsaved(version);
3696-
if (result.HasValue)
3697-
{
3698-
return result;
3699-
}
3700-
}
3701-
3702-
// check the id unsaved-value
3703-
bool? result2 = entityMetamodel.IdentifierProperty.UnsavedValue.IsUnsaved(id);
3704-
if (result2.HasValue)
3705-
{
3706-
if (IdentifierGenerator is Assigned)
3707-
{
3708-
// if using assigned identifier, we can only make assumptions
3709-
// if the value is a known unsaved-value
3710-
if (result2.Value)
3711-
return true;
3712-
}
3713-
else
3714-
{
3715-
return result2;
3716-
}
3717-
}
3689+
// check the id unsaved-value
3690+
// We do this first so we don't have to hydrate the version property if the id property already gives us the info we need (NH-3505).
3691+
bool? result2 = entityMetamodel.IdentifierProperty.UnsavedValue.IsUnsaved(id);
3692+
if (result2.HasValue)
3693+
{
3694+
if (IdentifierGenerator is Assigned)
3695+
{
3696+
// if using assigned identifier, we can only make assumptions
3697+
// if the value is a known unsaved-value
3698+
if (result2.Value)
3699+
return true;
3700+
}
3701+
else
3702+
{
3703+
return result2;
3704+
}
3705+
}
3706+
3707+
// check the version unsaved-value, if appropriate
3708+
if (IsVersioned)
3709+
{
3710+
object version = GetVersion(entity, session.EntityMode);
3711+
bool? result = entityMetamodel.VersionProperty.UnsavedValue.IsUnsaved(version);
3712+
if (result.HasValue)
3713+
{
3714+
return result;
3715+
}
3716+
}
37183717

37193718
// check to see if it is in the second-level cache
37203719
if (HasCache)

0 commit comments

Comments
 (0)