Skip to content

Commit 531161a

Browse files
committed
Merge branch 'gliljas-NH3571'
2 parents e888c42 + 03eb294 commit 531161a

File tree

5 files changed

+228
-1
lines changed

5 files changed

+228
-1
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
using System.Collections;
2+
using System.Linq;
3+
using NHibernate.Linq;
4+
using NUnit.Framework;
5+
using System.Linq.Expressions;
6+
using System;
7+
8+
namespace NHibernate.Test.NHSpecificTest.NH3571
9+
{
10+
[TestFixture]
11+
public class Fixture : TestCase
12+
{
13+
protected override string MappingsAssembly
14+
{
15+
get { return "NHibernate.Test"; }
16+
}
17+
18+
protected override IList Mappings
19+
{
20+
get
21+
{
22+
return new[]
23+
{
24+
"NHSpecificTest.NH3571.Mappings.hbm.xml"
25+
};
26+
}
27+
}
28+
29+
/// <summary>
30+
/// push some data into the database
31+
/// Really functions as a save test also
32+
/// </summary>
33+
protected override void OnSetUp()
34+
{
35+
base.OnSetUp();
36+
37+
using (var session = OpenSession())
38+
{
39+
using (var tran = session.BeginTransaction())
40+
{
41+
var product = new Product {ProductId = "1"};
42+
product.Details.Properties["Name"] = "First Product";
43+
product.Details.Properties["Description"] = "First Description";
44+
45+
session.Save(product);
46+
47+
product = new Product {ProductId = "2"};
48+
product.Details.Properties["Name"] = "Second Product";
49+
product.Details.Properties["Description"] = "Second Description";
50+
51+
session.Save(product);
52+
53+
product = new Product {ProductId = "3"};
54+
product.Details.Properties["Name"] = "val";
55+
product.Details.Properties["Description"] = "val";
56+
57+
session.Save(product);
58+
59+
tran.Commit();
60+
}
61+
}
62+
}
63+
64+
protected override void OnTearDown()
65+
{
66+
base.OnTearDown();
67+
68+
using (var session = OpenSession())
69+
{
70+
using (var tran = session.BeginTransaction())
71+
{
72+
session.Delete("from Product");
73+
tran.Commit();
74+
}
75+
}
76+
77+
}
78+
79+
[Test]
80+
public void CanQueryDynamicComponentInComponent()
81+
{
82+
using (var session = OpenSession())
83+
{
84+
var query = session.CreateQuery("from Product p where p.Details.Properties.Name=:name");
85+
query.SetString("name", "First Product");
86+
//var product = query.List<Product>().FirstOrDefault();
87+
var product =
88+
(from p in session.Query<Product>() where (string) p.Details.Properties["Name"] == "First Product" select p).Single();
89+
90+
Assert.IsNotNull(product);
91+
Assert.AreEqual("First Product", product.Details.Properties["Name"]);
92+
}
93+
}
94+
95+
96+
[Test]
97+
public void MultipleQueriesShouldNotCache()
98+
{
99+
using (var session = OpenSession())
100+
{
101+
// Query by name
102+
var product1 = (from p in session.Query<Product>()
103+
where (string) p.Details.Properties["Name"] == "First Product"
104+
select p).Single();
105+
Assert.That(product1.ProductId, Is.EqualTo("1"));
106+
107+
// Query by description (this test is to verify that the dictionary
108+
// index isn't cached from the query above.
109+
var product2 = (from p in session.Query<Product>()
110+
where (string) p.Details.Properties["Description"] == "Second Description"
111+
select p).Single();
112+
Assert.That(product2.ProductId, Is.EqualTo("2"));
113+
}
114+
}
115+
116+
117+
[Test]
118+
public void DifferentKeyInDynamicComponentDictionaryReturnsDifferentExpressionKeys()
119+
{
120+
using (var session = OpenSession())
121+
{
122+
// ReSharper disable AccessToDisposedClosure Ok since the expressions aren't actually used after the using block.
123+
Expression<Func<IEnumerable>> key1 = () => (from a in session.Query<Product>() where (string) a.Details.Properties["Name"] == "val" select a);
124+
Expression<Func<IEnumerable>> key2 = () => (from a in session.Query<Product>() where (string) a.Details.Properties["Description"] == "val" select a);
125+
// ReSharper restore AccessToDisposedClosure
126+
127+
var nhKey1 = new NhLinqExpression(key1.Body, sessions);
128+
var nhKey2 = new NhLinqExpression(key2.Body, sessions);
129+
130+
Assert.AreNotEqual(nhKey1.Key, nhKey2.Key);
131+
}
132+
}
133+
}
134+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
3+
namespace="NHibernate.Test.NHSpecificTest.NH3571">
4+
<class name="Product" table="Products">
5+
<id name="ProductId" column="ProductId" type="String">
6+
<generator class="assigned" />
7+
8+
</id>
9+
<component name="Details" class="ProductDetails">
10+
<dynamic-component name="Properties">
11+
<property name="Description" column="Description" type="String"/>
12+
<property name="Name" column="Name" type="String" />
13+
</dynamic-component>
14+
</component>
15+
</class>
16+
17+
</hibernate-mapping>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH3571
5+
{
6+
public class Product
7+
{
8+
public Product()
9+
{
10+
Details = new ProductDetails();
11+
}
12+
public virtual string ProductId { get; set; }
13+
14+
public virtual ProductDetails Details
15+
{
16+
get;
17+
set;
18+
}
19+
20+
public virtual IList<ProductDetails> DetailsList
21+
{
22+
get;
23+
set;
24+
}
25+
}
26+
27+
public class ProductDetails
28+
{
29+
private IDictionary _properties;
30+
31+
public virtual IDictionary Properties
32+
{
33+
get
34+
{
35+
if (_properties == null)
36+
_properties = new Hashtable();
37+
38+
return _properties;
39+
}
40+
set { _properties = value; }
41+
}
42+
}
43+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@
695695
<Compile Include="NHSpecificTest\NH1082\Domain.cs" />
696696
<Compile Include="NHSpecificTest\NH1082\Fixture.cs" />
697697
<Compile Include="NHSpecificTest\NH1082\SessionInterceptorThatThrowsExceptionAtBeforeTransactionCompletion.cs" />
698+
<Compile Include="NHSpecificTest\NH3571\Fixture.cs" />
699+
<Compile Include="NHSpecificTest\NH3571\Product.cs" />
698700
<Compile Include="NHSpecificTest\NH3459\Fixture.cs" />
699701
<Compile Include="NHSpecificTest\NH3459\Order.cs" />
700702
<Compile Include="NHSpecificTest\NH2692\Fixture.cs" />
@@ -3021,6 +3023,7 @@
30213023
</EmbeddedResource>
30223024
<EmbeddedResource Include="Unionsubclass\DatabaseKeyword.hbm.xml" />
30233025
<EmbeddedResource Include="NHSpecificTest\NH1082\Mappings.hbm.xml" />
3026+
<EmbeddedResource Include="NHSpecificTest\NH3571\Mappings.hbm.xml" />
30243027
<EmbeddedResource Include="NHSpecificTest\NH2692\Mappings.hbm.xml">
30253028
<SubType>Designer</SubType>
30263029
</EmbeddedResource>

src/NHibernate/Linq/Visitors/VisitorUtil.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections;
55
using System.Reflection;
66
using NHibernate.Util;
7+
using Remotion.Linq.Clauses.Expressions;
78

89
namespace NHibernate.Linq.Visitors
910
{
@@ -30,12 +31,41 @@ public static bool IsDynamicComponentDictionaryGetter(MethodInfo method, Express
3031
if (member == null)
3132
return false;
3233

34+
var memberPath = member.Member.Name;
3335
var metaData = sessionFactory.GetClassMetadata(member.Expression.Type);
36+
37+
//Walk backwards if the owning member is not a mapped class (i.e a possible Component)
38+
targetObject = member.Expression;
39+
while (metaData == null && targetObject != null &&
40+
(targetObject.NodeType == ExpressionType.MemberAccess || targetObject.NodeType == ExpressionType.Parameter ||
41+
targetObject.NodeType == QuerySourceReferenceExpression.ExpressionType))
42+
{
43+
System.Type memberType;
44+
if (targetObject.NodeType == QuerySourceReferenceExpression.ExpressionType)
45+
{
46+
var querySourceExpression = (QuerySourceReferenceExpression) targetObject;
47+
memberType = querySourceExpression.Type;
48+
}
49+
else if (targetObject.NodeType == ExpressionType.Parameter)
50+
{
51+
var parameterExpression = (ParameterExpression) targetObject;
52+
memberType = parameterExpression.Type;
53+
}
54+
else //targetObject.NodeType == ExpressionType.MemberAccess
55+
{
56+
var memberExpression = ((MemberExpression) targetObject);
57+
memberPath = memberExpression.Member.Name + "." + memberPath;
58+
memberType = memberExpression.Type;
59+
targetObject = memberExpression.Expression;
60+
}
61+
metaData = sessionFactory.GetClassMetadata(memberType);
62+
}
63+
3464
if (metaData == null)
3565
return false;
3666

3767
// IDictionary can be mapped as collection or component - is it mapped as a component?
38-
var propertyType = metaData.GetPropertyType(member.Member.Name);
68+
var propertyType = metaData.GetPropertyType(memberPath);
3969
return (propertyType != null && propertyType.IsComponentType);
4070
}
4171

0 commit comments

Comments
 (0)