Skip to content

Commit 703e75e

Browse files
committed
NH-2662: Casting a joined alias in QueryOver loses alias context and looks for property on QueryOver root
SVN: trunk@5908
1 parent 904a2ca commit 703e75e

File tree

7 files changed

+177
-21
lines changed

7 files changed

+177
-21
lines changed

src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs

+21-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ public void TestFindMemberExpressionReference()
2424
Assert.AreEqual("Name", property);
2525
}
2626

27+
[Test]
28+
public void TestFindMemberExpressionReferenceCast()
29+
{
30+
Expression<Func<Person, string>> e = (Person p) => ((CustomPerson)p).MiddleName;
31+
string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
32+
Assert.AreEqual("MiddleName", property);
33+
}
34+
2735
[Test]
2836
public void TestFindMemberExpressionReferenceAlias()
2937
{
@@ -33,6 +41,15 @@ public void TestFindMemberExpressionReferenceAlias()
3341
Assert.AreEqual("personAlias.Name", property);
3442
}
3543

44+
[Test]
45+
public void TestFindMemberExpressionReferenceCastAlias()
46+
{
47+
Person personAlias = null;
48+
Expression<Func<string>> e = () => ((CustomPerson)personAlias).MiddleName;
49+
string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
50+
Assert.AreEqual("personAlias.MiddleName", property);
51+
}
52+
3653
[Test]
3754
public void TestFindMemberExpressionComponent()
3855
{
@@ -157,17 +174,19 @@ public void TestFindMemberExpressionConstants()
157174
{
158175
var children = new List<Child> { new Child { Nickname = "test nickname" } };
159176
Person person =
160-
new Person()
177+
new CustomPerson()
161178
{
162179
Name = "test name",
180+
MiddleName = "test middle name",
163181
NullableAge = 4,
164182
Children = children,
165183
};
166184

167185
Assert.That(Projection(() => person.Name), Is.EqualTo("test name"));
186+
Assert.That(Projection(() => ((CustomPerson)person).MiddleName), Is.EqualTo("test middle name"));
168187
Assert.That(Projection(() => "test name"), Is.EqualTo("test name"));
169188
Assert.That(Projection(() => person.NullableAge.Value), Is.EqualTo(4));
170-
Assert.That(Projection(() => person.GetType()), Is.EqualTo(typeof(Person)));
189+
Assert.That(Projection(() => person.GetType()), Is.EqualTo(typeof(CustomPerson)));
171190
Assert.That(Projection(() => person.Children.First().Nickname), Is.EqualTo("test nickname"));
172191
Assert.That(Projection(() => children[0].Nickname), Is.EqualTo("test nickname"));
173192
}

src/NHibernate.Test/Criteria/Lambda/Model.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ public virtual Person AddChild(Child child)
5050

5151
}
5252

53-
public class CustomPerson : Person { }
53+
public class CustomPerson : Person
54+
{
55+
public virtual string MiddleName { get; set; }
56+
}
5457

5558
public class Child
5659
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH2662
5+
{
6+
public class Customer
7+
{
8+
public virtual Guid Id
9+
{
10+
get;
11+
protected set;
12+
}
13+
public virtual Order Order
14+
{
15+
get;
16+
set;
17+
}
18+
}
19+
20+
public class Order
21+
{
22+
public virtual Guid Id
23+
{
24+
get;
25+
protected set;
26+
}
27+
28+
public virtual DateTime OrderDate
29+
{
30+
get;
31+
set;
32+
}
33+
}
34+
35+
public class PizzaOrder: Order
36+
{
37+
public virtual string PizzaName
38+
{
39+
get;
40+
set;
41+
}
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Linq;
5+
using NHibernate.Linq;
6+
using NUnit.Framework;
7+
using SharpTestsEx;
8+
9+
namespace NHibernate.Test.NHSpecificTest.NH2662
10+
{
11+
public class Fixture : BugTestCase
12+
{
13+
[Test]
14+
public void WhenCastAliasInQueryOverThenDoNotThrow()
15+
{
16+
using (var session = OpenSession())
17+
using (var tx = session.BeginTransaction())
18+
{
19+
var customer = new Customer
20+
{
21+
Order = new PizzaOrder { OrderDate = DateTime.Now, PizzaName = "Margarita" }
22+
};
23+
24+
var customer2 = new Customer
25+
{
26+
Order = new Order { OrderDate = DateTime.Now.AddDays(1) }
27+
};
28+
29+
session.Save(customer);
30+
session.Save(customer2);
31+
session.Flush();
32+
33+
Executing.This(
34+
() =>
35+
{
36+
var temp = session.Query<Customer>().Select(
37+
c => new {c.Id, c.Order.OrderDate, ((PizzaOrder)c.Order).PizzaName })
38+
.ToArray();
39+
40+
foreach (var item in temp) { Trace.WriteLine(item.PizzaName);}
41+
})
42+
.Should().NotThrow();
43+
44+
Executing.This(
45+
() =>
46+
{
47+
Order orderAlias = null;
48+
49+
var results =
50+
session.QueryOver<Customer>()
51+
.Left.JoinAlias(o => o.Order, () => orderAlias)
52+
.OrderBy(() => orderAlias.OrderDate).Asc
53+
.SelectList(list =>
54+
list
55+
.Select(o => o.Id)
56+
.Select(() => orderAlias.OrderDate)
57+
.Select(() => ((PizzaOrder) orderAlias).PizzaName))
58+
.List<object[]>();
59+
60+
Assert.That(results.Count, Is.EqualTo(2));
61+
Assert.That(results[0][2], Is.EqualTo("Margarita"));
62+
63+
}).Should().NotThrow();
64+
}
65+
}
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
assembly="NHibernate.Test"
4+
namespace="NHibernate.Test.NHSpecificTest.NH2662">
5+
6+
<class name="Customer">
7+
<id name="Id">
8+
<generator class="guid" />
9+
</id>
10+
11+
<many-to-one name="Order" class="Order" column="OrderId" cascade="save-update" />
12+
13+
</class>
14+
15+
<class name="Order" table="Orders">
16+
<id name="Id">
17+
<generator class="guid" />
18+
</id>
19+
20+
<property name="OrderDate" />
21+
22+
<joined-subclass name="PizzaOrder" table="Pizzas">
23+
<key column="OrderId" />
24+
<property name="PizzaName" />
25+
</joined-subclass>
26+
27+
</class>
28+
29+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

+3
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,8 @@
847847
<Compile Include="NHSpecificTest\NH2632\Fixture.cs" />
848848
<Compile Include="NHSpecificTest\NH2660And2661\DomainClass.cs" />
849849
<Compile Include="NHSpecificTest\NH2660And2661\Test.cs" />
850+
<Compile Include="NHSpecificTest\NH2662\Domain.cs" />
851+
<Compile Include="NHSpecificTest\NH2662\Fixture.cs" />
850852
<Compile Include="NHSpecificTest\NH2673\Blog.cs" />
851853
<Compile Include="NHSpecificTest\NH2673\CachingWithTrasformerTests.cs" />
852854
<Compile Include="NHSpecificTest\NH2691\Domain.cs" />
@@ -2712,6 +2714,7 @@
27122714
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
27132715
</ItemGroup>
27142716
<ItemGroup>
2717+
<EmbeddedResource Include="NHSpecificTest\NH2662\Mappings.hbm.xml" />
27152718
<EmbeddedResource Include="NHSpecificTest\NH2703\Mappings.hbm.xml" />
27162719
<EmbeddedResource Include="NHSpecificTest\NH2736\Mappings.hbm.xml" />
27172720
<EmbeddedResource Include="NHSpecificTest\NH2721\Mappings.hbm.xml" />

src/NHibernate/Impl/ExpressionProcessor.cs

+10-18
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ public static string FindMemberExpression(Expression expression)
212212

213213
return FindMemberExpression(memberExpression.Expression) + "." + memberExpression.Member.Name;
214214
}
215+
else if (memberExpression.Expression.NodeType == ExpressionType.Convert)
216+
{
217+
return (FindMemberExpression(memberExpression.Expression) + "." + memberExpression.Member.Name).TrimStart('.');
218+
}
215219
else
216220
{
217221
return memberExpression.Member.Name;
@@ -244,6 +248,9 @@ public static string FindMemberExpression(Expression expression)
244248
throw new Exception("Unrecognised method call in expression " + expression.ToString());
245249
}
246250

251+
if (expression is ParameterExpression)
252+
return "";
253+
247254
throw new Exception("Could not determine member from " + expression.ToString());
248255
}
249256

@@ -322,26 +329,11 @@ private static bool IsMemberExpression(Expression expression)
322329
if (memberExpression.Expression == null)
323330
return false; // it's a member of a static class
324331

325-
if (memberExpression.Expression.NodeType == ExpressionType.Parameter)
332+
if (IsMemberExpression(memberExpression.Expression))
326333
return true;
327334

328-
if (IsNullableOfT(memberExpression.Member.DeclaringType))
329-
{
330-
// it's a Nullable<T>, so ignore any .Value
331-
if (memberExpression.Member.Name == "Value")
332-
return IsMemberExpression(memberExpression.Expression);
333-
}
334-
335-
if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
336-
{
337-
if (IsMemberExpression(memberExpression.Expression))
338-
return true;
339-
340-
// if the member has a null value, it was an alias
341-
return EvaluatesToNull(memberExpression.Expression);
342-
}
343-
344-
return IsMemberExpression(memberExpression.Expression);
335+
// if the member has a null value, it was an alias
336+
return EvaluatesToNull(memberExpression.Expression);
345337
}
346338

347339
if (expression is UnaryExpression)

0 commit comments

Comments
 (0)