Skip to content

Commit 9b3e835

Browse files
committed
Merge branch 'NH3571' of github.com:gliljas/nhibernate-core into gliljas-NH3571
2 parents e888c42 + 9e86b23 commit 9b3e835

File tree

5 files changed

+227
-1
lines changed

5 files changed

+227
-1
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
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+
Product product = new Product();
42+
product.ProductId = "1";
43+
product.Details.Properties["Name"] = "First Product";
44+
product.Details.Properties["Description"] = "First Description";
45+
46+
session.Save(product);
47+
48+
product = new Product();
49+
product.ProductId = "2";
50+
product.Details.Properties["Name"] = "Second Product";
51+
product.Details.Properties["Description"] = "Second Description";
52+
53+
session.Save(product);
54+
55+
product = new Product();
56+
product.ProductId = "3";
57+
product.Details.Properties["Name"] = "val";
58+
product.Details.Properties["Description"] = "val";
59+
60+
session.Save(product);
61+
62+
tran.Commit();
63+
}
64+
}
65+
}
66+
67+
protected override void OnTearDown()
68+
{
69+
base.OnTearDown();
70+
71+
using (var session = OpenSession())
72+
{
73+
using (var tran = session.BeginTransaction())
74+
{
75+
session.Delete("from Product");
76+
tran.Commit();
77+
}
78+
}
79+
80+
}
81+
82+
[Test]
83+
public void Query_DynamicComponent_In_Component()
84+
{
85+
using (var session = OpenSession())
86+
{
87+
var query = session.CreateQuery("from Product p where p.Details.Properties.Name=:name");
88+
query.SetString("name", "First Product");
89+
//var product = query.List<Product>().FirstOrDefault();
90+
var product =
91+
(from p in session.Query<Product>() where p.Details.Properties["Name"] == "First Product" select p).Single();
92+
93+
Assert.IsNotNull(product);
94+
Assert.AreEqual("First Product", product.Details.Properties["Name"]);
95+
}
96+
}
97+
98+
99+
100+
[Test]
101+
public void Multiple_Query_Does_Not_Cache()
102+
{
103+
using (var session = OpenSession())
104+
{
105+
// Query by name
106+
var product1 = (from p in session.Query<Product>()
107+
where p.Details.Properties["Name"] == "First Product"
108+
select p).Single();
109+
Assert.That(product1.ProductId, Is.EqualTo("1"));
110+
111+
// Query by description (this test is to verify that the dictionary
112+
// index isn't cached from the query above.
113+
var product2 = (from p in session.Query<Product>()
114+
where p.Details.Properties["Description"] == "Second Description"
115+
select p).Single();
116+
Assert.That(product2.ProductId, Is.EqualTo("2"));
117+
}
118+
}
119+
120+
[Test]
121+
public void Different_Key_In_DynamicComponentDictionary_Returns_Different_Keys()
122+
{
123+
using (var session = OpenSession())
124+
{
125+
Expression<Func<IEnumerable>> key1 = () => (from a in session.Query<Product>() where a.Details.Properties["Name"] == "val" select a);
126+
Expression<Func<IEnumerable>> key2 = () => (from a in session.Query<Product>() where a.Details.Properties["Description"] == "val" select a);
127+
128+
var nhKey1 = new NhLinqExpression(key1.Body, sessions);
129+
var nhKey2 = new NhLinqExpression(key2.Body, sessions);
130+
131+
Assert.AreNotEqual(nhKey1.Key, nhKey2.Key);
132+
}
133+
}
134+
}
135+
}
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: 29 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,39 @@ 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 && (targetObject.NodeType == ExpressionType.MemberAccess || targetObject.NodeType == ExpressionType.Parameter || (int)targetObject.NodeType == 100001))
40+
{
41+
System.Type memberType;
42+
if ((int)targetObject.NodeType == 100001)
43+
{
44+
var querySourceExpression = (QuerySourceReferenceExpression)targetObject;
45+
memberType = querySourceExpression.Type;
46+
}
47+
else if (targetObject.NodeType == ExpressionType.Parameter)
48+
{
49+
var parameterExpression = (ParameterExpression) targetObject;
50+
memberType = parameterExpression.Type;
51+
}
52+
else //targetObject.NodeType == ExpressionType.MemberAccess
53+
{
54+
var memberExpression = ((MemberExpression)targetObject);
55+
memberPath = memberExpression.Member.Name + "." + memberPath;
56+
memberType = memberExpression.Type;
57+
targetObject = memberExpression.Expression;
58+
}
59+
metaData = sessionFactory.GetClassMetadata(memberType);
60+
61+
}
3462
if (metaData == null)
3563
return false;
3664

3765
// IDictionary can be mapped as collection or component - is it mapped as a component?
38-
var propertyType = metaData.GetPropertyType(member.Member.Name);
66+
var propertyType = metaData.GetPropertyType(memberPath);
3967
return (propertyType != null && propertyType.IsComponentType);
4068
}
4169

0 commit comments

Comments
 (0)