Skip to content

Commit 0a1ada8

Browse files
Fix many-to-many with property-ref
Fixes #1214
1 parent 5596176 commit 0a1ada8

File tree

5 files changed

+32
-13
lines changed

5 files changed

+32
-13
lines changed

src/NHibernate.Test/Async/PropertyRef/ManyToManyPropertyRefFixture.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ FROM ManyBs manybs0_
9898
Assert.That(loadedManyA.ManyBs.Count, Is.EqualTo(3));
9999
}
100100

101-
[Test, Ignore("Not fixed yet")]
101+
[Test]
102102
public async Task Getting_a_ManyA_object_with_fetchmode_join_will_workAsync()
103103
{
104104
ManyA loadedManyA;
@@ -142,7 +142,7 @@ bei NHibernate.Persister.Entity.AbstractEntityPersister.LoadByUniqueKey(String p
142142
bei NHibernate.Type.EntityType.LoadByUniqueKey(String entityName, String uniqueKeyPropertyName, Object key, ISessionImplementor session) in C:\Users\Armin\Projects\NHibernate\branches\2.1.x\nhibernate\src\NHibernate\Type\EntityType.cs:Zeile 552.
143143
*/
144144

145-
Assert.That(loadedManyA.ManyBs.Count, Is.EqualTo(3));
145+
Assert.That(loadedManyA.ManyBs, Has.Count.EqualTo(3).And.None.Null);
146146
}
147147
}
148148
}

src/NHibernate.Test/PropertyRef/ManyToManyPropertyRefFixture.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ FROM ManyBs manybs0_
8787
Assert.That(loadedManyA.ManyBs.Count, Is.EqualTo(3));
8888
}
8989

90-
[Test, Ignore("Not fixed yet")]
90+
[Test]
9191
public void Getting_a_ManyA_object_with_fetchmode_join_will_work()
9292
{
9393
ManyA loadedManyA;
@@ -131,7 +131,7 @@ bei NHibernate.Persister.Entity.AbstractEntityPersister.LoadByUniqueKey(String p
131131
bei NHibernate.Type.EntityType.LoadByUniqueKey(String entityName, String uniqueKeyPropertyName, Object key, ISessionImplementor session) in C:\Users\Armin\Projects\NHibernate\branches\2.1.x\nhibernate\src\NHibernate\Type\EntityType.cs:Zeile 552.
132132
*/
133133

134-
Assert.That(loadedManyA.ManyBs.Count, Is.EqualTo(3));
134+
Assert.That(loadedManyA.ManyBs, Has.Count.EqualTo(3).And.None.Null);
135135
}
136136
}
137137
}

src/NHibernate.Test/PropertyRef/ManyToManyWithPropertyRef.hbm.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<id name="Id">
66
<generator class="native"/>
77
</id>
8-
<property name="Number" column="`Number`"/>
8+
<property name="Number" column="`Number`" unique="true"/>
99
<property name="Value" column="`Value`"/>
1010
<bag name="ManyBs">
1111
<key column="ManyANumber" property-ref="Number"/>
@@ -17,7 +17,7 @@
1717
<id name="Id">
1818
<generator class="native"/>
1919
</id>
20-
<property name="Number" column="`Number`"/>
20+
<property name="Number" column="`Number`" unique="true"/>
2121
<property name="Value" column="`Value`"/>
2222
</class>
2323
</hibernate-mapping>

src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -821,13 +821,14 @@ private void BindManyToMany(HbmManyToMany manyToManyMapping, Mapping.Collection
821821
var restrictedLaziness = manyToManyMapping.lazySpecified ? manyToManyMapping.lazy : (HbmRestrictedLaziness?) null;
822822
InitLaziness(restrictedLaziness, manyToMany, true);
823823

824-
if(!string.IsNullOrEmpty(manyToManyMapping.propertyref))
824+
manyToMany.ReferencedEntityName = GetEntityName(manyToManyMapping, mappings);
825+
826+
if (!string.IsNullOrEmpty(manyToManyMapping.propertyref))
825827
{
826828
manyToMany.ReferencedPropertyName = manyToManyMapping.propertyref;
829+
mappings.AddUniquePropertyReference(manyToMany.ReferencedEntityName, manyToMany.ReferencedPropertyName);
827830
}
828831

829-
manyToMany.ReferencedEntityName = GetEntityName(manyToManyMapping, mappings);
830-
831832
manyToMany.IsIgnoreNotFound = manyToManyMapping.NotFoundMode == HbmNotFoundMode.Ignore;
832833

833834
if(!string.IsNullOrEmpty(manyToManyMapping.foreignkey))

src/NHibernate/Persister/Collection/BasicCollectionPersister.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,18 +271,36 @@ public override string SelectFragment(IJoinable rhs, string rhsAlias, string lhs
271271
IAssociationType elementType = (IAssociationType) ElementType;
272272
if (rhs.Equals(elementType.GetAssociatedJoinable(Factory)))
273273
{
274-
return ManyToManySelectFragment(rhs, rhsAlias, lhsAlias, collectionSuffix);
274+
return ManyToManySelectFragment(rhs, rhsAlias, lhsAlias, collectionSuffix, elementType);
275275
}
276276
}
277277
return includeCollectionColumns ? SelectFragment(lhsAlias, collectionSuffix) : string.Empty;
278278
}
279279

280-
private string ManyToManySelectFragment(IJoinable rhs, string rhsAlias, string lhsAlias, string collectionSuffix)
280+
private string ManyToManySelectFragment(
281+
IJoinable rhs,
282+
string rhsAlias,
283+
string lhsAlias,
284+
string collectionSuffix,
285+
IAssociationType elementType)
281286
{
282287
SelectFragment frag = GenerateSelectFragment(lhsAlias, collectionSuffix);
283288

284-
string[] _elementColumnNames = rhs.KeyColumnNames;
285-
frag.AddColumns(rhsAlias, _elementColumnNames, elementColumnAliases);
289+
// We need to select in the associated entity table instead of taking the collection actual element,
290+
// because filters can be applied to the entity table outer join. In such case, we need to return null
291+
// for filtered-out elements. (It is tempting to switch to an inner join and just use
292+
// SelectFragment(lhsAlias, collectionSuffix) for many-to-many too, but this would hinder the proper
293+
// handling of the not-found feature.)
294+
var elementColumnNames = string.IsNullOrEmpty(elementType.RHSUniqueKeyPropertyName)
295+
? rhs.KeyColumnNames
296+
// rhs is the entity persister, it does not handle being referenced through an unique key by a
297+
// collection and always yield its identifier columns as KeyColumnNames. We need to resolve the
298+
// key columns instead.
299+
// 6.0 TODO: consider breaking again that IJoinable.SelectFragment interface for transmitting
300+
// the OuterJoinableAssociation instead of its Joinable property. This would allow to get the
301+
// adequate columns directly instead of re-computing them.
302+
: ((IPropertyMapping) rhs).ToColumns(elementType.RHSUniqueKeyPropertyName);
303+
frag.AddColumns(rhsAlias, elementColumnNames, elementColumnAliases);
286304
AppendIndexColumns(frag, lhsAlias);
287305
AppendIdentifierColumns(frag, lhsAlias);
288306

0 commit comments

Comments
 (0)