Skip to content

Commit 8b22343

Browse files
author
Dmitry Naumov
committed
More correct fix based on collection mapping information
1 parent ef9779c commit 8b22343

File tree

5 files changed

+67
-10
lines changed

5 files changed

+67
-10
lines changed

src/NHibernate.Test/NHSpecificTest/NH3408/Fixture.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ public void ProjectAnonymousTypeWithArrayProperty()
1212
{
1313
using (var session = OpenSession())
1414
{
15-
var query = from p in session.Query<Person>()
16-
select new { p.Photo };
15+
var query = from c in session.Query<Country>()
16+
select new { c.Picture, c.NationalHolidays };
1717

1818
var result = query.ToList();
1919
}

src/NHibernate.Test/NHSpecificTest/NH3408/Mappings.hbm.xml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
33
namespace="NHibernate.Test.NHSpecificTest.NH3408"
44
assembly="NHibernate.Test">
5-
<class name="Person">
5+
<class name="Country">
66
<id name="Id">
77
<generator class="increment"/>
88
</id>
99
<property name="Name"/>
10-
<property name="Photo"/>
10+
<property name="Picture"/>
11+
<set name="NationalHolidays" table="Holiday">
12+
<key column="CalendarID" />
13+
<element type="System.DateTime">
14+
<column name="Holiday" sql-type="smalldatetime" />
15+
</element>
16+
</set>
1117
</class>
1218

1319
</hibernate-mapping>
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
namespace NHibernate.Test.NHSpecificTest.NH3408
22
{
3-
public class Person
3+
using System;
4+
5+
public class Country
46
{
57
public virtual int Id { get; set; }
68

79
public virtual string Name { get; set; }
810

9-
public virtual byte[] Photo { get; set; }
11+
public virtual byte[] Picture { get; set; }
12+
13+
public virtual DateTime[] NationalHolidays { get; set; }
1014
}
1115
}

src/NHibernate/Linq/NestedSelects/NestedSelectDetector.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,18 @@
55

66
namespace NHibernate.Linq.NestedSelects
77
{
8+
using System.Reflection;
9+
using NHibernate.Metadata;
10+
811
internal class NestedSelectDetector : NhExpressionTreeVisitor
912
{
1013
private readonly ICollection<Expression> _expressions = new List<Expression>();
14+
private readonly IDictionary<string, ICollectionMetadata> _collectionMetadata;
15+
16+
public NestedSelectDetector(IDictionary<string, ICollectionMetadata> collectionMetadata)
17+
{
18+
_collectionMetadata = collectionMetadata;
19+
}
1120

1221
public ICollection<Expression> Expressions
1322
{
@@ -33,13 +42,20 @@ protected override Expression VisitMemberExpression(MemberExpression expression)
3342
{
3443
var memberType = expression.Member.GetPropertyOrFieldType();
3544

36-
if (memberType != null && memberType.IsCollectionType())
45+
if (memberType != null && memberType.IsCollectionType() && IsMappedCollection(expression.Member))
3746
{
3847
Expressions.Add(expression);
3948
}
4049
}
4150

4251
return base.VisitMemberExpression(expression);
4352
}
53+
54+
private bool IsMappedCollection(MemberInfo memberInfo)
55+
{
56+
var key = memberInfo.DeclaringType.FullName + "." + memberInfo.Name;
57+
58+
return _collectionMetadata.ContainsKey(key);
59+
}
4460
}
4561
}

src/NHibernate/Linq/NestedSelects/NestedSelectRewriter.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal static class NestedSelectRewriter
1919

2020
public static void ReWrite(QueryModel queryModel, ISessionFactory sessionFactory)
2121
{
22-
var nsqmv = new NestedSelectDetector();
22+
var nsqmv = new NestedSelectDetector(sessionFactory.GetAllCollectionMetadata());
2323
nsqmv.VisitExpression(queryModel.SelectClause.Selector);
2424
if (!nsqmv.HasSubqueries)
2525
return;
@@ -113,7 +113,7 @@ private static Expression ProcessSubquery(ISessionFactory sessionFactory, IColle
113113
private static Expression ProcessMemberExpression(ISessionFactory sessionFactory, ICollection<ExpressionHolder> elementExpression, QueryModel queryModel, Expression @group, Expression memberExpression)
114114
{
115115
var join = new NhJoinClause(new NameGenerator(queryModel).GetNewName(),
116-
memberExpression.Type.GetGenericArguments()[0],
116+
GetElementType((MemberExpression) memberExpression),
117117
memberExpression);
118118

119119
queryModel.BodyClauses.Add(@join);
@@ -161,8 +161,18 @@ private static Expression SubCollectionQuery(System.Type collectionType, System.
161161
Expression.Call(whereMethod, source, predicate),
162162
selector);
163163

164+
if (collectionType.IsArray)
165+
{
166+
var toArrayMethod = EnumerableHelper.GetMethod("ToArray",
167+
new[] { typeof(IEnumerable<>) },
168+
new[] { elementType });
169+
170+
var array = Expression.Call(toArrayMethod, @select);
171+
return array;
172+
}
173+
164174
var toListMethod = EnumerableHelper.GetMethod("ToList",
165-
new[] { typeof (IEnumerable<>) },
175+
new[] { typeof(IEnumerable<>) },
166176
new[] { elementType });
167177

168178
var list = Expression.Call(toListMethod, @select);
@@ -237,5 +247,26 @@ private static Expression ConvertToObject(Expression expression)
237247
{
238248
return Expression.Convert(expression, typeof(object));
239249
}
250+
251+
private static System.Type GetElementType(MemberExpression expression)
252+
{
253+
var type = expression.Type;
254+
if (!type.IsCollectionType())
255+
{
256+
throw new ArgumentException();
257+
}
258+
259+
if (type.IsGenericType)
260+
{
261+
return type.GetGenericArguments()[0];
262+
}
263+
264+
if (type.IsArray)
265+
{
266+
return type.GetElementType();
267+
}
268+
269+
throw new NotSupportedException("Unknown collection type " + type.FullName);
270+
}
240271
}
241272
}

0 commit comments

Comments
 (0)