Skip to content

Commit b12486e

Browse files
committed
NH-3946: Linq where is base class doesn't get subclasses. Adapted logic from SingleTableEntityPersister.DiscriminatorFilterFragment to find subclasses. Seems to work with JoinedSubclassEntityPersister as well
1 parent 4c42ed7 commit b12486e

File tree

5 files changed

+47
-3
lines changed

5 files changed

+47
-3
lines changed

src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,44 @@ protected HqlTreeNode VisitExpression(Expression expression)
147147

148148
private HqlTreeNode VisitTypeBinaryExpression(TypeBinaryExpression expression)
149149
{
150+
var meta = SessionFactory.GetClassMetadata(expression.TypeOperand) as Persister.Entity.AbstractEntityPersister;
151+
if (meta != null && !meta.IsExplicitPolymorphism)
152+
{
153+
//Adapted the logic found in SingleTableEntityPersister.DiscriminatorFilterFragment
154+
var Factory = SessionFactory as NHibernate.Engine.ISessionFactoryImplementor;
155+
var nodes = new System.Collections.Generic.List<HqlIdent>();
156+
foreach (var typeName in meta.SubclassClosure)
157+
{
158+
var persister = (NHibernate.Persister.Entity.IQueryable)Factory.GetEntityPersister(typeName);
159+
if (persister.IsAbstract) continue;
160+
nodes.Add(_hqlTreeBuilder.Ident(persister.EntityName));
161+
}
162+
163+
if (nodes.Count == 1)
164+
{
165+
return _hqlTreeBuilder.Equality(
166+
_hqlTreeBuilder.Dot(Visit(expression.Expression).AsExpression(), _hqlTreeBuilder.Class()),
167+
nodes[0]);
168+
}
169+
else if (nodes.Count > 1)
170+
{
171+
return _hqlTreeBuilder.In(
172+
_hqlTreeBuilder.Dot(
173+
Visit(expression.Expression).AsExpression(),
174+
_hqlTreeBuilder.Class()),
175+
_hqlTreeBuilder.ExpressionSubTreeHolder(nodes.ToArray()));
176+
}
177+
else
178+
{
179+
const string abstractClassWithNoSubclassExceptionMessageTemplate =
180+
@"The class {0} can't be instatiated and does not have mapped subclasses;
181+
possible solutions:
182+
- don't map the abstract class
183+
- map its subclasses.";
184+
185+
throw new NotSupportedException(string.Format(abstractClassWithNoSubclassExceptionMessageTemplate, meta.EntityName));
186+
}
187+
}
150188
return _hqlTreeBuilder.Equality(
151189
_hqlTreeBuilder.Dot(Visit(expression.Expression).AsExpression(), _hqlTreeBuilder.Class()),
152190
_hqlTreeBuilder.Ident(expression.TypeOperand.FullName));

src/NHibernate/Persister/Entity/AbstractEntityPersister.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ public int[] NaturalIdentifierProperties
10131013
public abstract string[] ConstraintOrderedTableNameClosure { get;}
10141014
public abstract string DiscriminatorSQLValue { get;}
10151015
public abstract object DiscriminatorValue { get;}
1016+
public abstract string[] SubclassClosure { get; }
10161017
public abstract string[] PropertySpaces { get;}
10171018

10181019
protected virtual void AddDiscriminatorToInsert(SqlInsertBuilder insert) { }

src/NHibernate/Persister/Entity/JoinedSubclassEntityPersister.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,11 @@ public override object DiscriminatorValue
345345
get { return discriminatorValue; }
346346
}
347347

348+
public override string[] SubclassClosure
349+
{
350+
get { return subclassClosure; }
351+
}
352+
348353
public override string[] PropertySpaces
349354
{
350355
get

src/NHibernate/Persister/Entity/SingleTableEntityPersister.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ public override object DiscriminatorValue
424424
get { return discriminatorValue; }
425425
}
426426

427-
public virtual string[] SubclassClosure
427+
public override string[] SubclassClosure
428428
{
429429
get { return subclassClosure; }
430430
}
@@ -618,7 +618,7 @@ private string DiscriminatorFilterFragment(string alias)
618618
@"The class {0} can't be instatiated and does not have mapped subclasses;
619619
possible solutions:
620620
- don't map the abstract class
621-
- map the its subclasses.";
621+
- map its subclasses.";
622622

623623
if (NeedsDiscriminator)
624624
{

src/NHibernate/Persister/Entity/UnionSubclassEntityPersister.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ public override object DiscriminatorValue
186186
get { return discriminatorValue; }
187187
}
188188

189-
public string[] SubclassClosure
189+
public override string[] SubclassClosure
190190
{
191191
get { return subclassClosure; }
192192
}

0 commit comments

Comments
 (0)