Skip to content

Commit 09d5f5d

Browse files
neilcrowtherhazzik
authored andcommitted
NH-3741 - Many to many mapping with interfaces or XML bindings
1 parent d4090f5 commit 09d5f5d

16 files changed

+466
-364
lines changed

src/NHibernate.Test/MappingByCode/IntegrationTests/NH3667/MapFixture.cs

Lines changed: 233 additions & 307 deletions
Large diffs are not rendered by default.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System.Linq;
2+
using NHibernate.Cfg.MappingSchema;
3+
using NHibernate.Mapping.ByCode;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.MappingByCode.IntegrationTests.NH3741
7+
{
8+
[TestFixture]
9+
public class MapFixture
10+
{
11+
[Test]
12+
public void TestMapManyToManyGenericCollectionBasedOnInterface()
13+
{
14+
var mapper = new ModelMapper();
15+
16+
mapper.Class<ParentWithInterfaceChild>(c =>
17+
{
18+
c.Id(x => x.Id, x => x.Generator(Generators.Identity));
19+
c.IdBag(x => x.Children, bag => { }, rel => rel.ManyToMany());
20+
});
21+
22+
mapper.Class<Child>(c =>
23+
{
24+
c.Id(x => x.Id, x => x.Generator(Generators.Identity));
25+
c.Property(x => x.Description);
26+
});
27+
28+
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(ParentWithInterfaceChild), typeof(Child) });
29+
var hbmClass = hbmMapping.RootClasses[0];
30+
var hbmIdbag = hbmClass.Properties.OfType<HbmIdbag>().SingleOrDefault();
31+
32+
Assert.That(hbmIdbag, Is.Not.Null);
33+
Assert.That(hbmIdbag.ElementRelationship, Is.InstanceOf<HbmManyToMany>());
34+
}
35+
36+
[Test]
37+
public void TestMapManyToManyGenericCollectionBasedOnEntity()
38+
{
39+
var mapper = new ModelMapper();
40+
41+
mapper.Class<ParentWithEntityChild>(c =>
42+
{
43+
c.Id(x => x.Id, x => x.Generator(Generators.Identity));
44+
c.IdBag(x => x.Children, bag => { }, rel => rel.ManyToMany());
45+
});
46+
47+
mapper.Class<Child>(c =>
48+
{
49+
c.Id(x => x.Id, x => x.Generator(Generators.Identity));
50+
c.Property(x => x.Description);
51+
});
52+
53+
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(ParentWithEntityChild), typeof(Child) });
54+
var hbmClass = hbmMapping.RootClasses[0];
55+
var hbmIdbag = hbmClass.Properties.OfType<HbmIdbag>().SingleOrDefault();
56+
57+
Assert.That(hbmIdbag, Is.Not.Null);
58+
Assert.That(hbmIdbag.ElementRelationship, Is.InstanceOf<HbmManyToMany>());
59+
}
60+
61+
[Test]
62+
public void TestMapManyToManyGenericCollectionBasedOnItem()
63+
{
64+
var mapper = new ModelMapper();
65+
66+
mapper.Class<ParentWithItemChild>(c =>
67+
{
68+
c.Id(x => x.Id, x => x.Generator(Generators.Identity));
69+
c.IdBag(x => x.Children, bag => { }, rel => rel.ManyToMany());
70+
});
71+
72+
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(ParentWithItemChild) });
73+
var hbmClass = hbmMapping.RootClasses[0];
74+
var hbmIdbag = hbmClass.Properties.OfType<HbmIdbag>().SingleOrDefault();
75+
76+
Assert.That(hbmIdbag, Is.Not.Null);
77+
Assert.That(hbmIdbag.ElementRelationship, Is.InstanceOf<HbmManyToMany>());
78+
}
79+
}
80+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Collections.Generic;
2+
3+
namespace NHibernate.Test.MappingByCode.IntegrationTests.NH3741
4+
{
5+
public class ParentWithInterfaceChild
6+
{
7+
public int Id { get; set; }
8+
public List<IChild> Children { get; set; }
9+
}
10+
11+
public class ParentWithEntityChild
12+
{
13+
public int Id { get; set; }
14+
public List<Child> Children { get; set; }
15+
}
16+
17+
public class ParentWithItemChild
18+
{
19+
public int Id { get; set; }
20+
public List<string> Children { get; set; }
21+
}
22+
23+
public interface IChild
24+
{
25+
int Id { get; set; }
26+
string Description { get; set; }
27+
}
28+
29+
public class Child : IChild
30+
{
31+
public int Id { get; set; }
32+
public string Description { get; set; }
33+
}
34+
}

src/NHibernate.Test/MappingByCode/ModelExplicitDeclarationsHolderMergeTest.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ public ExplicitDeclarationsHolderMock()
2222
private readonly HashSet<MemberInfo> dictionaries = new HashSet<MemberInfo>();
2323
private readonly HashSet<MemberInfo> idBags = new HashSet<MemberInfo>();
2424
private readonly HashSet<MemberInfo> lists = new HashSet<MemberInfo>();
25-
private readonly HashSet<MemberInfo> manyToManyRelations = new HashSet<MemberInfo>();
25+
private readonly HashSet<MemberInfo> keyManyToManyRelations = new HashSet<MemberInfo>();
26+
private readonly HashSet<MemberInfo> itemManyToManyRelations = new HashSet<MemberInfo>();
2627
private readonly HashSet<MemberInfo> manyToAnyRelations = new HashSet<MemberInfo>();
2728
private readonly HashSet<MemberInfo> manyToOneRelations = new HashSet<MemberInfo>();
2829
private readonly HashSet<MemberInfo> naturalIds = new HashSet<MemberInfo>();
@@ -108,12 +109,21 @@ public IEnumerable<MemberInfo> ManyToOneRelations
108109
}
109110
}
110111

111-
public IEnumerable<MemberInfo> ManyToManyRelations
112+
public IEnumerable<MemberInfo> KeyManyToManyRelations
112113
{
113114
get
114115
{
115-
PropertiesGettersUsed.Add("ManyToManyRelations");
116-
return manyToManyRelations;
116+
PropertiesGettersUsed.Add("KeyManyToManyRelations");
117+
return keyManyToManyRelations;
118+
}
119+
}
120+
121+
public IEnumerable<MemberInfo> ItemManyToManyRelations
122+
{
123+
get
124+
{
125+
PropertiesGettersUsed.Add("ItemManyToManyRelations");
126+
return itemManyToManyRelations;
117127
}
118128
}
119129

@@ -292,7 +302,8 @@ public void AddAsTablePerClassHierarchyEntity(System.Type type) { }
292302
public void AddAsTablePerConcreteClassEntity(System.Type type) { }
293303
public void AddAsOneToOneRelation(MemberInfo member) { }
294304
public void AddAsManyToOneRelation(MemberInfo member) { }
295-
public void AddAsManyToManyRelation(MemberInfo member) { }
305+
public void AddAsManyToManyKeyRelation(MemberInfo member) { }
306+
public void AddAsManyToManyItemRelation(MemberInfo member) {}
296307
public void AddAsOneToManyRelation(MemberInfo member) { }
297308
public void AddAsManyToAnyRelation(MemberInfo member) {}
298309

@@ -493,10 +504,10 @@ public void MergeManyToManyRelations()
493504
{
494505
var destination = new ExplicitDeclarationsHolder();
495506
var source = new ExplicitDeclarationsHolder();
496-
source.AddAsManyToManyRelation(property);
507+
source.AddAsManyToManyItemRelation(property);
497508

498509
destination.Merge(source);
499-
Assert.That(destination.ManyToManyRelations, Has.Count.EqualTo(1));
510+
Assert.That(destination.ItemManyToManyRelations, Has.Count.EqualTo(1));
500511
}
501512

502513
[Test]

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,8 @@
637637
<Compile Include="MappingByCode\IntegrationTests\NH3280\OneToOneToInheritedProperty.cs" />
638638
<Compile Include="MappingByCode\IntegrationTests\NH3667\MapFixture.cs" />
639639
<Compile Include="MappingByCode\IntegrationTests\NH3667\Model.cs" />
640+
<Compile Include="MappingByCode\IntegrationTests\NH3741\MapFixture.cs" />
641+
<Compile Include="MappingByCode\IntegrationTests\NH3741\Model.cs" />
640642
<Compile Include="MappingByCode\MappersTests\AnyMapperTest.cs" />
641643
<Compile Include="MappingByCode\MappersTests\IdMapperTest.cs" />
642644
<Compile Include="MappingByCode\MappersTests\ManyToOneMapperTest.cs" />

src/NHibernate/Mapping/ByCode/AbstractExplicitlyDeclaredModel.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ public abstract class AbstractExplicitlyDeclaredModel : IModelExplicitDeclaratio
1515
private readonly HashSet<MemberInfo> dictionaries = new HashSet<MemberInfo>();
1616
private readonly HashSet<MemberInfo> idBags = new HashSet<MemberInfo>();
1717
private readonly HashSet<MemberInfo> lists = new HashSet<MemberInfo>();
18-
private readonly HashSet<MemberInfo> manyToManyRelations = new HashSet<MemberInfo>();
18+
private readonly HashSet<MemberInfo> keyManyToManyRelations = new HashSet<MemberInfo>();
19+
private readonly HashSet<MemberInfo> itemManyToManyRelations = new HashSet<MemberInfo>();
1920
private readonly HashSet<MemberInfo> manyToAnyRelations = new HashSet<MemberInfo>();
2021
private readonly HashSet<MemberInfo> manyToOneRelations = new HashSet<MemberInfo>();
2122
private readonly HashSet<MemberInfo> naturalIds = new HashSet<MemberInfo>();
@@ -81,9 +82,14 @@ public IEnumerable<MemberInfo> ManyToOneRelations
8182
get { return manyToOneRelations; }
8283
}
8384

84-
public IEnumerable<MemberInfo> ManyToManyRelations
85+
public IEnumerable<MemberInfo> KeyManyToManyRelations
8586
{
86-
get { return manyToManyRelations; }
87+
get { return keyManyToManyRelations; }
88+
}
89+
90+
public IEnumerable<MemberInfo> ItemManyToManyRelations
91+
{
92+
get { return itemManyToManyRelations; }
8793
}
8894

8995
public IEnumerable<MemberInfo> OneToManyRelations
@@ -332,10 +338,16 @@ public void AddAsManyToOneRelation(MemberInfo member)
332338
manyToOneRelations.Add(member);
333339
}
334340

335-
public void AddAsManyToManyRelation(MemberInfo member)
341+
public void AddAsManyToManyKeyRelation(MemberInfo member)
342+
{
343+
persistentMembers.Add(member);
344+
keyManyToManyRelations.Add(member);
345+
}
346+
347+
public void AddAsManyToManyItemRelation(MemberInfo member)
336348
{
337349
persistentMembers.Add(member);
338-
manyToManyRelations.Add(member);
350+
itemManyToManyRelations.Add(member);
339351
}
340352

341353
public void AddAsOneToManyRelation(MemberInfo member)

src/NHibernate/Mapping/ByCode/ExplicitlyDeclaredModel.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ public virtual bool IsManyToOne(MemberInfo member)
5656
return ManyToOneRelations.Contains(member);
5757
}
5858

59-
public virtual bool IsManyToMany(MemberInfo member)
59+
public virtual bool IsManyToManyItem(MemberInfo member)
6060
{
61-
return ManyToManyRelations.Contains(member);
61+
return ItemManyToManyRelations.Contains(member);
62+
}
63+
64+
public virtual bool IsManyToManyKey(MemberInfo member)
65+
{
66+
return KeyManyToManyRelations.Contains(member);
6267
}
6368

6469
public virtual bool IsOneToMany(MemberInfo member)

src/NHibernate/Mapping/ByCode/FakeModelExplicitDeclarationsHolder.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using System.Collections.Generic;
32
using System.Linq;
43
using System.Reflection;
@@ -14,7 +13,8 @@ public class FakeModelExplicitDeclarationsHolder : IModelExplicitDeclarationsHol
1413
private readonly IEnumerable<MemberInfo> dictionaries = Enumerable.Empty<MemberInfo>();
1514
private readonly IEnumerable<MemberInfo> idBags = Enumerable.Empty<MemberInfo>();
1615
private readonly IEnumerable<MemberInfo> lists = Enumerable.Empty<MemberInfo>();
17-
private readonly IEnumerable<MemberInfo> manyToManyRelations = Enumerable.Empty<MemberInfo>();
16+
private readonly IEnumerable<MemberInfo> keyManyToManyRelations = Enumerable.Empty<MemberInfo>();
17+
private readonly IEnumerable<MemberInfo> itemManyToManyRelations = Enumerable.Empty<MemberInfo>();
1818
private readonly IEnumerable<MemberInfo> manyToOneRelations = Enumerable.Empty<MemberInfo>();
1919
private readonly IEnumerable<MemberInfo> manyToAnyRelations = Enumerable.Empty<MemberInfo>();
2020
private readonly IEnumerable<MemberInfo> naturalIds = Enumerable.Empty<MemberInfo>();
@@ -76,9 +76,14 @@ public IEnumerable<MemberInfo> ManyToOneRelations
7676
get { return manyToOneRelations; }
7777
}
7878

79-
public IEnumerable<MemberInfo> ManyToManyRelations
79+
public IEnumerable<MemberInfo> KeyManyToManyRelations
8080
{
81-
get { return manyToManyRelations; }
81+
get { return keyManyToManyRelations; }
82+
}
83+
84+
public IEnumerable<MemberInfo> ItemManyToManyRelations
85+
{
86+
get { return itemManyToManyRelations; }
8287
}
8388

8489
public IEnumerable<MemberInfo> OneToManyRelations
@@ -195,7 +200,9 @@ public void AddAsOneToOneRelation(MemberInfo member) {}
195200

196201
public void AddAsManyToOneRelation(MemberInfo member) {}
197202

198-
public void AddAsManyToManyRelation(MemberInfo member) {}
203+
public void AddAsManyToManyKeyRelation(MemberInfo member) {}
204+
205+
public void AddAsManyToManyItemRelation(MemberInfo member) {}
199206

200207
public void AddAsOneToManyRelation(MemberInfo member) {}
201208

src/NHibernate/Mapping/ByCode/IModelExplicitDeclarationsHolder.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ public interface IModelExplicitDeclarationsHolder
2727

2828
IEnumerable<MemberInfo> OneToOneRelations { get; }
2929
IEnumerable<MemberInfo> ManyToOneRelations { get; }
30-
IEnumerable<MemberInfo> ManyToManyRelations { get; }
30+
IEnumerable<MemberInfo> KeyManyToManyRelations { get; }
31+
IEnumerable<MemberInfo> ItemManyToManyRelations { get; }
3132
IEnumerable<MemberInfo> OneToManyRelations { get; }
3233
IEnumerable<MemberInfo> ManyToAnyRelations { get; }
3334

@@ -61,7 +62,8 @@ public interface IModelExplicitDeclarationsHolder
6162

6263
void AddAsOneToOneRelation(MemberInfo member);
6364
void AddAsManyToOneRelation(MemberInfo member);
64-
void AddAsManyToManyRelation(MemberInfo member);
65+
void AddAsManyToManyKeyRelation(MemberInfo member);
66+
void AddAsManyToManyItemRelation(MemberInfo member);
6567
void AddAsOneToManyRelation(MemberInfo member);
6668
void AddAsManyToAnyRelation(MemberInfo member);
6769

src/NHibernate/Mapping/ByCode/IModelInspector.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ public interface IModelInspector
1616

1717
bool IsOneToOne(MemberInfo member);
1818
bool IsManyToOne(MemberInfo member);
19-
bool IsManyToMany(MemberInfo member);
19+
bool IsManyToManyItem(MemberInfo member);
20+
bool IsManyToManyKey(MemberInfo member);
2021
bool IsOneToMany(MemberInfo member);
2122
bool IsManyToAny(MemberInfo member);
2223

src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/ManyToManyCustomizer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public ManyToManyCustomizer(IModelExplicitDeclarationsHolder explicitDeclaration
1313
{
1414
throw new ArgumentNullException("explicitDeclarationsHolder");
1515
}
16-
explicitDeclarationsHolder.AddAsManyToManyRelation(propertyPath.LocalMember);
16+
explicitDeclarationsHolder.AddAsManyToManyItemRelation(propertyPath.LocalMember);
1717
this.propertyPath = propertyPath;
1818
this.customizersHolder = customizersHolder;
1919
}

src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/MapKeyManyToManyCustomizer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public MapKeyManyToManyCustomizer(IModelExplicitDeclarationsHolder explicitDecla
1313
{
1414
throw new ArgumentNullException("explicitDeclarationsHolder");
1515
}
16-
explicitDeclarationsHolder.AddAsManyToManyRelation(propertyPath.LocalMember);
16+
explicitDeclarationsHolder.AddAsManyToManyKeyRelation(propertyPath.LocalMember);
1717
this.propertyPath = propertyPath;
1818
this.customizersHolder = customizersHolder;
1919
}

src/NHibernate/Mapping/ByCode/Impl/ExplicitDeclarationsHolder.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ public class ExplicitDeclarationsHolder : IModelExplicitDeclarationsHolder
1414
private readonly HashSet<MemberInfo> dictionaries = new HashSet<MemberInfo>();
1515
private readonly HashSet<MemberInfo> idBags = new HashSet<MemberInfo>();
1616
private readonly HashSet<MemberInfo> lists = new HashSet<MemberInfo>();
17-
private readonly HashSet<MemberInfo> manyToManyRelations = new HashSet<MemberInfo>();
17+
private readonly HashSet<MemberInfo> keyManyToManyRelations = new HashSet<MemberInfo>();
18+
private readonly HashSet<MemberInfo> itemManyToManyRelations = new HashSet<MemberInfo>();
1819
private readonly HashSet<MemberInfo> manyToOneRelations = new HashSet<MemberInfo>();
1920
private readonly HashSet<MemberInfo> manyToAnyRelations = new HashSet<MemberInfo>();
2021
private readonly HashSet<MemberInfo> naturalIds = new HashSet<MemberInfo>();
@@ -71,9 +72,14 @@ public IEnumerable<MemberInfo> ManyToOneRelations
7172
get { return manyToOneRelations; }
7273
}
7374

74-
public IEnumerable<MemberInfo> ManyToManyRelations
75+
public IEnumerable<MemberInfo> KeyManyToManyRelations
7576
{
76-
get { return manyToManyRelations; }
77+
get { return keyManyToManyRelations; }
78+
}
79+
80+
public IEnumerable<MemberInfo> ItemManyToManyRelations
81+
{
82+
get { return itemManyToManyRelations; }
7783
}
7884

7985
public IEnumerable<MemberInfo> OneToManyRelations
@@ -213,9 +219,14 @@ public void AddAsManyToOneRelation(MemberInfo member)
213219
manyToOneRelations.Add(member);
214220
}
215221

216-
public void AddAsManyToManyRelation(MemberInfo member)
222+
public void AddAsManyToManyKeyRelation(MemberInfo member)
223+
{
224+
keyManyToManyRelations.Add(member);
225+
}
226+
227+
public void AddAsManyToManyItemRelation(MemberInfo member)
217228
{
218-
manyToManyRelations.Add(member);
229+
itemManyToManyRelations.Add(member);
219230
}
220231

221232
public void AddAsOneToManyRelation(MemberInfo member)

src/NHibernate/Mapping/ByCode/ModelExplicitDeclarationsHolderExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public static void Merge(this IModelExplicitDeclarationsHolder destination, IMod
1919

2020
System.Array.ForEach(source.OneToOneRelations.ToArray(), destination.AddAsOneToOneRelation);
2121
System.Array.ForEach(source.ManyToOneRelations.ToArray(), destination.AddAsManyToOneRelation);
22-
System.Array.ForEach(source.ManyToManyRelations.ToArray(), destination.AddAsManyToManyRelation);
22+
System.Array.ForEach(source.KeyManyToManyRelations.ToArray(), destination.AddAsManyToManyKeyRelation);
23+
System.Array.ForEach(source.ItemManyToManyRelations.ToArray(), destination.AddAsManyToManyItemRelation);
2324
System.Array.ForEach(source.ManyToAnyRelations.ToArray(), destination.AddAsManyToAnyRelation);
2425
System.Array.ForEach(source.OneToManyRelations.ToArray(), destination.AddAsOneToManyRelation);
2526
System.Array.ForEach(source.Any.ToArray(), destination.AddAsAny);

0 commit comments

Comments
 (0)