Skip to content

Commit 232d648

Browse files
Fixes incorrect tracking of identifiers when performing add/insert/remove operations on PersistentIdentifierBag collection. Thanks go to Patrick Earl for this one (ref. NH2279, NH2111)
SVN: trunk@5173
1 parent 648faf7 commit 232d648

File tree

7 files changed

+308
-20
lines changed

7 files changed

+308
-20
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
namespace NHibernate.Test.NHSpecificTest.NH2279
6+
{
7+
public class B
8+
{
9+
private int? _id;
10+
private string _name;
11+
private IList<C> _cs = new List<C>();
12+
13+
public B()
14+
{
15+
}
16+
17+
public B(string name)
18+
{
19+
Name = name;
20+
}
21+
22+
public int? Id
23+
{
24+
get { return _id; }
25+
set { _id = value; }
26+
}
27+
28+
public string Name
29+
{
30+
get { return _name; }
31+
set { _name = value; }
32+
}
33+
34+
public IList<C> Cs
35+
{
36+
get { return _cs; }
37+
set { _cs = value; }
38+
}
39+
}
40+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Collections;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH2279
5+
{
6+
public class C
7+
{
8+
private int? _id;
9+
private string _name;
10+
11+
public C()
12+
{
13+
}
14+
15+
public C(string name)
16+
{
17+
Name = name;
18+
}
19+
20+
public int? Id
21+
{
22+
get { return _id; }
23+
set { _id = value; }
24+
}
25+
26+
public string Name
27+
{
28+
get { return _name; }
29+
set { _name = value; }
30+
}
31+
}
32+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Collections;
4+
5+
using NUnit.Framework;
6+
7+
namespace NHibernate.Test.NHSpecificTest.NH2279
8+
{
9+
[TestFixture]
10+
public class Fixture : BugTestCase
11+
{
12+
protected override void OnTearDown()
13+
{
14+
using( ISession s = sessions.OpenSession() )
15+
{
16+
s.Delete( "from A" );
17+
s.Flush();
18+
}
19+
}
20+
21+
[Test]
22+
public void IdBagIndexTracking()
23+
{
24+
A a = new A("a");
25+
a.Name = "first generic type";
26+
a.Items.Add("a");
27+
a.Items.Add("b");
28+
a.Items.Add("c");
29+
30+
ISession s = OpenSession();
31+
s.SaveOrUpdate(a);
32+
s.Flush();
33+
s.Close();
34+
35+
s = OpenSession();
36+
a = (A)s.Load(typeof(A), a.Id);
37+
CollectionAssert.AreEquivalent(new[] {"a", "b", "c"}, a.Items);
38+
39+
// Add and remove a "transient" item.
40+
a.Items.Add("d");
41+
a.Items.Remove("d");
42+
43+
// Remove persisted items and then insert a transient item.
44+
a.Items.Remove("b");
45+
a.Items.Remove("a");
46+
a.Items.Insert(0, "e");
47+
48+
// Add a couple transient items and insert another transient item between them.
49+
a.Items.Add("f");
50+
a.Items.Add("g");
51+
a.Items.Insert(3, "h");
52+
53+
// Save and then see if we get what we expect.
54+
s.SaveOrUpdate(a);
55+
s.Flush();
56+
s.Close();
57+
58+
s = OpenSession();
59+
a = (A)s.Load(typeof(A), a.Id);
60+
CollectionAssert.AreEquivalent(new [] {"c", "e", "f", "g", "h"}, a.Items);
61+
62+
// Test changing a value by index directly.
63+
a.Items[2] = "i";
64+
65+
string[] expected = a.Items.Cast<string>().ToArray();
66+
67+
s.SaveOrUpdate(a);
68+
s.Flush();
69+
s.Close();
70+
71+
s = OpenSession();
72+
a = (A)s.Load(typeof(A), a.Id);
73+
CollectionAssert.AreEquivalent(expected, a.Items);
74+
75+
s.Flush();
76+
s.Close();
77+
}
78+
79+
[Test]
80+
public void CartesianProduct()
81+
{
82+
A a1 = new A("a1");
83+
A a2 = new A("a2");
84+
B b1 = new B("b1");
85+
B b2 = new B("b2");
86+
B b3 = new B("b3");
87+
B b4 = new B("b4");
88+
C c1 = new C("c1");
89+
C c2 = new C("c2");
90+
C c3 = new C("c3");
91+
C c4 = new C("c4");
92+
C c5 = new C("c5");
93+
C c6 = new C("c6");
94+
95+
a1.Bs.Add(b1);
96+
a2.Bs.Add(b2);
97+
a2.Bs.Add(b2);
98+
99+
a1.Bs.Add(b3);
100+
a2.Bs.Add(b3);
101+
102+
a1.Bs.Add(b4);
103+
a2.Bs.Add(b4);
104+
a1.Bs.Add(b4);
105+
a2.Bs.Add(b4);
106+
107+
b1.Cs.Add(c1);
108+
b2.Cs.Add(c2);
109+
b2.Cs.Add(c2);
110+
b3.Cs.Add(c3);
111+
b3.Cs.Add(c3);
112+
b3.Cs.Add(c3);
113+
b4.Cs.Add(c4);
114+
b4.Cs.Add(c4);
115+
b4.Cs.Add(c4);
116+
b4.Cs.Add(c4);
117+
118+
b1.Cs.Add(c5);
119+
b2.Cs.Add(c5);
120+
b3.Cs.Add(c5);
121+
b4.Cs.Add(c5);
122+
123+
b1.Cs.Add(c6);
124+
b2.Cs.Add(c6);
125+
b3.Cs.Add(c6);
126+
b4.Cs.Add(c6);
127+
b1.Cs.Add(c6);
128+
b2.Cs.Add(c6);
129+
b3.Cs.Add(c6);
130+
b4.Cs.Add(c6);
131+
132+
ISession s = OpenSession();
133+
s.Save(a1);
134+
s.Save(a2);
135+
s.Flush();
136+
s.Close();
137+
138+
s = OpenSession();
139+
IList<A> results = s.CreateQuery("from A a join fetch a.Bs b join fetch b.Cs").List<A>().Distinct().ToList();
140+
141+
Assert.That(results, Has.Count.EqualTo(2));
142+
A ta1 = results.Single(a => a.Name == "a1");
143+
A ta2 = results.Single(a => a.Name == "a2");
144+
145+
Assert.That(ta1.Bs.Select(b => b.Name).ToArray(), Is.EquivalentTo(new[] { "b1", "b3", "b4", "b4" }));
146+
Assert.That(ta2.Bs.Select(b => b.Name).ToArray(), Is.EquivalentTo(new[] { "b2", "b2", "b3", "b4", "b4" }));
147+
B tb1 = ta1.Bs.First(b => b.Name == "b1");
148+
B tb2 = ta2.Bs.First(b => b.Name == "b2");
149+
B tb3 = ta1.Bs.First(b => b.Name == "b3");
150+
B tb4 = ta1.Bs.First(b => b.Name == "b4");
151+
152+
Assert.That(tb1.Cs.Select(c => c.Name).ToArray(), Is.EquivalentTo(new[] { "c1", "c5", "c6", "c6" }));
153+
Assert.That(tb2.Cs.Select(c => c.Name).ToArray(), Is.EquivalentTo(new[] { "c2", "c2", "c5", "c6", "c6" }));
154+
Assert.That(tb3.Cs.Select(c => c.Name).ToArray(), Is.EquivalentTo(new[] { "c3", "c3", "c3", "c5", "c6", "c6" }));
155+
Assert.That(tb4.Cs.Select(c => c.Name).ToArray(), Is.EquivalentTo(new[] { "c4", "c4", "c4", "c4", "c5", "c6", "c6" }));
156+
s.Close();
157+
}
158+
}
159+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping
3+
xmlns="urn:nhibernate-mapping-2.2"
4+
assembly="NHibernate.Test"
5+
namespace="NHibernate.Test.NHSpecificTest.NH2279">
6+
7+
<class name="A" table="a" lazy="false">
8+
<id name="Id" column="id" unsaved-value="null">
9+
<generator class="native" />
10+
</id>
11+
<property name="Name" column="name" />
12+
<idbag name="Items" cascade="all-delete-orphan">
13+
<collection-id type="Int32" column="item_id">
14+
<generator class="increment" />
15+
</collection-id>
16+
<key column="a_id" />
17+
<element type="string" />
18+
</idbag>
19+
<idbag name="Bs" cascade="all-delete-orphan">
20+
<collection-id type="Int32" column="item_id">
21+
<generator class="increment" />
22+
</collection-id>
23+
<key column="a_id" />
24+
<many-to-many class="B" column="b_id" />
25+
</idbag>
26+
</class>
27+
28+
<class name="B" table="b" lazy="false">
29+
<id name="Id" column="id" unsaved-value="null">
30+
<generator class="native" />
31+
</id>
32+
<property name="Name" column="name" />
33+
<idbag name="Cs" cascade="all-delete-orphan">
34+
<collection-id type="Int32" column="item_id">
35+
<generator class="increment" />
36+
</collection-id>
37+
<key column="b_id" />
38+
<many-to-many class="C" column="c_id" />
39+
</idbag>
40+
</class>
41+
42+
<class name="C" table="c" lazy="false">
43+
<id name="Id" column="id" unsaved-value="null">
44+
<generator class="native" />
45+
</id>
46+
<property name="Name" column="name" />
47+
</class>
48+
49+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,10 @@
463463
<Compile Include="NHSpecificTest\NH2245\Model.cs" />
464464
<Compile Include="NHSpecificTest\NH2266\Domain.cs" />
465465
<Compile Include="NHSpecificTest\NH2266\Fixture.cs" />
466+
<Compile Include="NHSpecificTest\NH2279\A.cs" />
467+
<Compile Include="NHSpecificTest\NH2279\B.cs" />
468+
<Compile Include="NHSpecificTest\NH2279\C.cs" />
469+
<Compile Include="NHSpecificTest\NH2279\Fixture.cs" />
466470
<Compile Include="NHSpecificTest\NH2287\Domain.cs" />
467471
<Compile Include="NHSpecificTest\NH2287\Fixture.cs" />
468472
<Compile Include="NHSpecificTest\NH2293\Fixture.cs" />
@@ -1745,6 +1749,7 @@
17451749
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
17461750
</None>
17471751
<EmbeddedResource Include="NHSpecificTest\NH2224\Mappings.hbm.xml" />
1752+
<EmbeddedResource Include="NHSpecificTest\NH2279\Mappings.hbm.xml" />
17481753
</ItemGroup>
17491754
<ItemGroup>
17501755
<ProjectReference Include="..\NHibernate.ByteCode.Castle\NHibernate.ByteCode.Castle.csproj">
@@ -2588,6 +2593,7 @@
25882593
<EmbeddedResource Include="DynamicEntity\Tuplizer\Customer.hbm.xml" />
25892594
</ItemGroup>
25902595
<ItemGroup>
2596+
<Folder Include="NHSpecificTest\NH2279" />
25912597
<Folder Include="Properties\" />
25922598
</ItemGroup>
25932599
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

src/NHibernate/Collection/Generic/PersistentGenericIdentifierBag.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ int IList<T>.IndexOf(T item)
7878
void IList<T>.Insert(int index, T item)
7979
{
8080
Write();
81-
BeforeAdd(index);
81+
BeforeInsert(index);
8282
gvalues.Insert(index, item);
8383
}
8484

0 commit comments

Comments
 (0)