Skip to content

Commit cf26aa3

Browse files
committed
Fix dirty checking when property's previous state is uninitialized (NH-2860)
1 parent 00ebbbb commit cf26aa3

File tree

5 files changed

+125
-5
lines changed

5 files changed

+125
-5
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace NHibernate.Test.NHSpecificTest.NH2860
2+
{
3+
public class ClassA
4+
{
5+
public virtual int ID{ get; set; }
6+
public virtual string Text { get; set; }
7+
public virtual byte[] Blob_Field { get; set; }
8+
}
9+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
3+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH2860">
4+
5+
<class name="ClassA" table="A" lazy="true" dynamic-update="true" polymorphism="explicit">
6+
<id name="ID" column="ID" type="int" unsaved-value="0">
7+
<generator class="native" >
8+
<param name="sequence">gen_a_id</param>
9+
</generator>
10+
</id>
11+
<property name="Text" column="TEXT" type="string" length="200" not-null="false"/>
12+
<property name="Blob_Field" column="BLOB_FIELD" type="BinaryBlob" not-null="false" lazy="true"/>
13+
14+
</class>
15+
</hibernate-mapping>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using NUnit.Framework;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH2860
4+
{
5+
[TestFixture]
6+
public class SampleTest : BugTestCase
7+
{
8+
private int objId;
9+
10+
protected override void OnSetUp()
11+
{
12+
using (var session = OpenSession())
13+
using (var transaction = session.BeginTransaction())
14+
{
15+
var obj = new ClassA();
16+
obj.Text = "Test existing object";
17+
obj.Blob_Field = new byte[] { 0, 0, 1, 1, 2, 2 };
18+
objId = (int) session.Save(obj);
19+
transaction.Commit();
20+
}
21+
}
22+
23+
protected override void OnTearDown()
24+
{
25+
using (var session = OpenSession())
26+
using (var transaction = session.BeginTransaction())
27+
{
28+
session.Delete("from ClassA");
29+
transaction.Commit();
30+
}
31+
}
32+
33+
[Test]
34+
public void Can_LazyPropertyCastingException()
35+
{
36+
//following causes exception "Unable to cast object of type 'System.Object' to type 'System.Byte[]'.
37+
//notice that ClassA.Blob_Field s declared as lazy property
38+
//similar to fixed NH-2510 (?)
39+
//PS. Exception is beeing thrown only if object was created within the same session
40+
41+
using (var session = OpenSession())
42+
{
43+
var classA = new ClassA();
44+
classA.Text = "new entity";
45+
classA.Blob_Field = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
46+
using (var trans = session.BeginTransaction())
47+
{
48+
session.Save(classA);
49+
trans.Commit();
50+
}
51+
52+
session.Refresh(classA);
53+
54+
classA.Text = "updated entity";
55+
using (var trans = session.BeginTransaction())
56+
{
57+
session.SaveOrUpdate(classA);
58+
trans.Commit();
59+
}
60+
61+
session.Refresh(classA);
62+
}
63+
}
64+
65+
[Test]
66+
public void Can_LazyPropertyNotCastingException()
67+
{
68+
//here none exception beeing thrown
69+
using (var session = OpenSession())
70+
{
71+
var classA = session.Get<ClassA>(objId);
72+
Assert.IsNotNull(classA);
73+
74+
session.Refresh(classA);
75+
76+
classA.Text = "updated entity";
77+
using (var trans = session.BeginTransaction())
78+
{
79+
session.SaveOrUpdate(classA);
80+
trans.Commit();
81+
}
82+
83+
session.Refresh(classA);
84+
}
85+
}
86+
}
87+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,8 @@
10071007
<Compile Include="NHSpecificTest\NH3016\Fixture.cs" />
10081008
<Compile Include="NHSpecificTest\NH3145\Fixture.cs" />
10091009
<Compile Include="NHSpecificTest\NH3145\Model.cs" />
1010+
<Compile Include="NHSpecificTest\NH2860\ClassA.cs" />
1011+
<Compile Include="NHSpecificTest\NH2860\SampleTest.cs" />
10101012
<Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" />
10111013
<Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" />
10121014
<Compile Include="NHSpecificTest\Properties\Model.cs" />
@@ -2857,6 +2859,7 @@
28572859
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
28582860
</ItemGroup>
28592861
<ItemGroup>
2862+
<EmbeddedResource Include="NHSpecificTest\NH2860\Mappings.hbm.xml" />
28602863
<EmbeddedResource Include="NHSpecificTest\NH3332\Mappings.hbm.xml" />
28612864
<EmbeddedResource Include="NHSpecificTest\NH3050\Mappings.hbm.xml" />
28622865
<EmbeddedResource Include="NHSpecificTest\NH2651\Mappings.hbm.xml" />

src/NHibernate/Type/TypeHelper.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,7 @@ public static int[] FindDirty(StandardProperty[] properties,
238238

239239
for (int i = 0; i < span; i++)
240240
{
241-
bool dirty =
242-
!Equals(LazyPropertyInitializer.UnfetchedProperty, currentState[i]) &&
243-
properties[i].IsDirtyCheckable(anyUninitializedProperties)
244-
&& properties[i].Type.IsDirty(previousState[i], currentState[i], includeColumns[i], session);
245-
241+
var dirty = Dirty(properties, currentState, previousState, includeColumns, anyUninitializedProperties, session, i);
246242
if (dirty)
247243
{
248244
if (results == null)
@@ -264,6 +260,16 @@ public static int[] FindDirty(StandardProperty[] properties,
264260
}
265261
}
266262

263+
private static bool Dirty(StandardProperty[] properties, object[] currentState, object[] previousState, bool[][] includeColumns, bool anyUninitializedProperties, ISessionImplementor session, int i)
264+
{
265+
if (Equals(LazyPropertyInitializer.UnfetchedProperty, currentState[i]))
266+
return false;
267+
if (Equals(LazyPropertyInitializer.UnfetchedProperty, previousState[i]))
268+
return true;
269+
return properties[i].IsDirtyCheckable(anyUninitializedProperties) &&
270+
properties[i].Type.IsDirty(previousState[i], currentState[i], includeColumns[i], session);
271+
}
272+
267273
/// <summary>
268274
/// <para>Determine if any of the given field values are modified, returning an array containing
269275
/// indices of the modified fields.</para>

0 commit comments

Comments
 (0)