Skip to content

Commit 76ce833

Browse files
committed
NH-3650 - Not share ComponentAsId between root classes if Id is defined in parent class
1 parent 71994bd commit 76ce833

File tree

4 files changed

+138
-8
lines changed

4 files changed

+138
-8
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
using System;
2+
using System.Linq;
3+
using NHibernate;
4+
using NHibernate.Cfg.MappingSchema;
5+
using NHibernate.Linq;
6+
using NHibernate.Mapping.ByCode;
7+
using NHibernate.Mapping.ByCode.Conformist;
8+
using NUnit.Framework;
9+
10+
namespace NHibernate.Test.MappingByCode.ExplicitlyDeclaredModelTests
11+
{
12+
public abstract class Parent
13+
{
14+
public virtual ParentId Id { get; set; }
15+
public virtual string Name { get; set; }
16+
public virtual Address Address { get; set; }
17+
}
18+
19+
public class ParentId
20+
{
21+
public string Key1 { get; set; }
22+
public string Key2 { get; set; }
23+
24+
public override bool Equals(object obj)
25+
{
26+
var pk = obj as ParentId;
27+
28+
if (obj == null)
29+
return false;
30+
31+
return (Key1 == pk.Key1 && Key2 == pk.Key2);
32+
}
33+
34+
public override int GetHashCode()
35+
{
36+
return (Key1 + "|" + Key2).GetHashCode();
37+
}
38+
}
39+
40+
public class Child1 : Parent
41+
{
42+
}
43+
44+
public class Child2 : Parent
45+
{
46+
}
47+
48+
class Child1Map : ClassMapping<Child1>
49+
{
50+
public Child1Map()
51+
{
52+
Table("Child1");
53+
54+
ComponentAsId<ParentId>(x => x.Id, pk =>
55+
{
56+
pk.Property(x => x.Key1, x => x.Column("key1"));
57+
pk.Property(x => x.Key2, x =>
58+
{
59+
x.Column("key2");
60+
});
61+
});
62+
63+
Property(x => x.Name);
64+
65+
Component<Address>(x => x.Address, map =>
66+
{
67+
map.Property(y => y.City, mc => mc.Column("city1"));
68+
});
69+
}
70+
}
71+
72+
class Child2Map : ClassMapping<Child2>
73+
{
74+
public Child2Map()
75+
{
76+
Table("Child2");
77+
78+
ComponentAsId<ParentId>(x => x.Id, pk =>
79+
{
80+
pk.Property(x => x.Key1, x => x.Column("key1"));
81+
pk.Property(x => x.Key2, x =>
82+
{
83+
x.Column("key2__");
84+
});
85+
});
86+
87+
Property(x => x.Name);
88+
89+
Component<Address>(x => x.Address, map =>
90+
{
91+
map.Property(y => y.City, mc => mc.Column("city2"));
92+
});
93+
}
94+
}
95+
96+
public class Address
97+
{
98+
public virtual string City { get; set; }
99+
}
100+
101+
[TestFixture]
102+
public class ComponentAsIdTest
103+
{
104+
[Test]
105+
public void CanHaveSameComponentAsIdMultipleTimesWithDifferentColumnNamesForSameProperty()
106+
{
107+
//NH-3650
108+
var model = new ModelMapper();
109+
model.AddMapping<Child1Map>();
110+
model.AddMapping<Child2Map>();
111+
112+
var mappings = model.CompileMappingForEach(new[] { typeof(Child1), typeof(Child2) });
113+
114+
var child1Mapping = mappings.ElementAt(0);
115+
Assert.AreEqual("city1", child1Mapping.RootClasses[0].Properties.OfType<HbmComponent>().First().Properties.OfType<HbmProperty>().Single().column);
116+
//next one fails
117+
Assert.AreEqual("key2", child1Mapping.RootClasses[0].CompositeId.Items.OfType<HbmKeyProperty>().Last().column1);
118+
119+
var child2Mapping = mappings.ElementAt(1);
120+
Assert.AreEqual("city2", child2Mapping.RootClasses[0].Properties.OfType<HbmComponent>().First().Properties.OfType<HbmProperty>().Single().column);
121+
Assert.AreEqual("key2__", child2Mapping.RootClasses[0].CompositeId.Items.OfType<HbmKeyProperty>().Last().column1);
122+
}
123+
}
124+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@
557557
<Compile Include="MappingByCode\ConventionModelMapperTests\PropertyToFieldAccessorTest.cs" />
558558
<Compile Include="MappingByCode\ConventionModelMapperTests\SafePoidTests.cs" />
559559
<Compile Include="MappingByCode\ConventionModelMapperTests\VersionOnBaseClassIntegrationTest.cs" />
560+
<Compile Include="MappingByCode\ExplicitlyDeclaredModelTests\ComponentAsIdTest.cs" />
560561
<Compile Include="MappingByCode\ExplicitMappingTests\AllPropertiesRegistrationTests.cs" />
561562
<Compile Include="MappingByCode\ExplicitMappingTests\BagOfNestedComponentsWithParentTest.cs" />
562563
<Compile Include="MappingByCode\ExplicitMappingTests\ClassWithComponentsTest.cs" />

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,8 @@ public void ComponentAsId<TComponent>(Expression<Func<TEntity, TComponent>> idPr
6464

6565
public void ComponentAsId<TComponent>(Expression<Func<TEntity, TComponent>> idProperty, Action<IComponentAsIdMapper<TComponent>> idMapper) where TComponent : class
6666
{
67-
var member = TypeExtensions.DecodeMemberAccessExpression(idProperty);
68-
var propertyPath = new PropertyPath(null, member);
69-
idMapper(new ComponentAsIdCustomizer<TComponent>(ExplicitDeclarationsHolder, CustomizersHolder, propertyPath));
67+
var memberOf = TypeExtensions.DecodeMemberAccessExpressionOf(idProperty);
68+
RegisterComponentAsIdMapping(idMapper, memberOf);
7069
}
7170

7271
public void ComponentAsId<TComponent>(string notVisiblePropertyOrFieldName) where TComponent : class
@@ -77,8 +76,16 @@ public void ComponentAsId<TComponent>(string notVisiblePropertyOrFieldName) wher
7776
public void ComponentAsId<TComponent>(string notVisiblePropertyOrFieldName, Action<IComponentAsIdMapper<TComponent>> idMapper) where TComponent : class
7877
{
7978
var member = typeof(TEntity).GetPropertyOrFieldMatchingName(notVisiblePropertyOrFieldName);
80-
var propertyPath = new PropertyPath(null, member);
81-
idMapper(new ComponentAsIdCustomizer<TComponent>(ExplicitDeclarationsHolder, CustomizersHolder, propertyPath));
79+
RegisterComponentAsIdMapping(idMapper, member);
80+
}
81+
82+
private void RegisterComponentAsIdMapping<TComponent>(Action<IComponentAsIdMapper<TComponent>> idMapper, params MemberInfo[] members) where TComponent : class
83+
{
84+
foreach (var member in members)
85+
{
86+
var propertyPath = new PropertyPath(PropertyPath, member);
87+
idMapper(new ComponentAsIdCustomizer<TComponent>(ExplicitDeclarationsHolder, CustomizersHolder, propertyPath));
88+
}
8289
}
8390

8491
public void ComposedId(Action<IComposedIdMapper<TEntity>> idPropertiesMapping)

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ public class DefaultCandidatePersistentMembersProvider : ICandidatePersistentMem
1616

1717
public IEnumerable<MemberInfo> GetEntityMembersForPoid(System.Type entityClass)
1818
{
19-
return entityClass.IsInterface
20-
? entityClass.GetInterfaceProperties()
21-
: entityClass.GetPropertiesOfHierarchy().Concat(GetFieldsOfHierarchy(entityClass));
19+
return GetCandidatePersistentProperties(entityClass, RootClassPropertiesBindingFlags).Concat(GetFieldsOfHierarchy(entityClass));
2220
}
2321

2422
public IEnumerable<MemberInfo> GetRootEntityMembers(System.Type entityClass)

0 commit comments

Comments
 (0)