From: <ric...@us...> - 2011-05-25 21:16:08
|
Revision: 5871 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5871&view=rev Author: ricbrown Date: 2011-05-25 21:16:01 +0000 (Wed, 25 May 2011) Log Message: ----------- NH-2733 (NH-2683): Using an expression in QueryOver gives: Lambda Parameter not in scope Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-25 12:47:06 UTC (rev 5870) +++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-25 21:16:01 UTC (rev 5871) @@ -334,10 +334,14 @@ if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess) { + if (IsMemberExpression(memberExpression.Expression)) + return true; + // if the member has a null value, it was an alias - if (EvaluatesToNull(memberExpression.Expression)) - return true; + return EvaluatesToNull(memberExpression.Expression); } + + return IsMemberExpression(memberExpression.Expression); } if (expression is UnaryExpression) @@ -358,9 +362,16 @@ if (_customProjectionProcessors.ContainsKey(signature)) return true; + if (methodCallExpression.Method.Name == "First") + { + if (IsMemberExpression(methodCallExpression.Arguments[0])) + return true; + + return EvaluatesToNull(methodCallExpression.Arguments[0]); + } + if (methodCallExpression.Method.Name == "GetType" - || methodCallExpression.Method.Name == "get_Item" - || methodCallExpression.Method.Name == "First") + || methodCallExpression.Method.Name == "get_Item") { if (IsMemberExpression(methodCallExpression.Object)) return true; Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs 2011-05-25 12:47:06 UTC (rev 5870) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs 2011-05-25 21:16:01 UTC (rev 5871) @@ -1,5 +1,6 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -19,35 +20,165 @@ public void TestFindMemberExpressionReference() { Expression<Func<Person, string>> e = (Person p) => p.Name; - string property = ExpressionProcessor.FindMemberExpression(e.Body); + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); Assert.AreEqual("Name", property); } [Test] + public void TestFindMemberExpressionReferenceAlias() + { + Person personAlias = null; + Expression<Func<string>> e = () => personAlias.Name; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.Name", property); + } + + [Test] + public void TestFindMemberExpressionComponent() + { + Expression<Func<Person, string>> e = (Person p) => p.Father.Name; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("Father.Name", property); + } + + [Test] + public void TestFindMemberExpressionComponentAlias() + { + Person personAlias = null; + Expression<Func<string>> e = () => personAlias.Father.Name; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.Father.Name", property); + } + + [Test] public void TestFindMemberExpressionValue() { Expression<Func<Person, object>> e = (Person p) => p.Age; - string property = ExpressionProcessor.FindMemberExpression(e.Body); + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); Assert.AreEqual("Age", property); } [Test] + public void TestFindMemberExpressionValueAlias() + { + Person personAlias = null; + Expression<Func<object>> e = () => personAlias.Age; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.Age", property); + } + + [Test] public void TestFindMemberExpressionSubCollectionIndex() { Expression<Func<Person, object>> e = (Person p) => p.PersonList[0].Children; - string property = ExpressionProcessor.FindMemberExpression(e.Body); + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); Assert.AreEqual("PersonList.Children", property); } [Test] + public void TestFindMemberExpressionSubCollectionIndexAlias() + { + Person personAlias = null; + Expression<Func<object>> e = () => personAlias.PersonList[0].Children; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.PersonList.Children", property); + } + + [Test] + public void TestFindMemberExpressionSubCollectionFirst() + { + Expression<Func<Person, object>> e = (Person p) => p.PersonList.First().Children; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("PersonList.Children", property); + } + + [Test] + public void TestFindMemberExpressionSubCollectionFirstAlias() + { + Person personAlias = null; + Expression<Func<object>> e = () => personAlias.PersonList.First().Children; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.PersonList.Children", property); + } + + [Test] public void TestFindMemberExpressionSubCollectionExtensionMethod() { Expression<Func<Person, object>> e = (Person p) => p.PersonList.First().Children; - string property = ExpressionProcessor.FindMemberExpression(e.Body); + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); Assert.AreEqual("PersonList.Children", property); } [Test] + public void TestFindMemberExpressionSubCollectionExtensionMethodAlias() + { + Person personAlias = null; + Expression<Func<object>> e = () => personAlias.PersonList.First().Children; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.PersonList.Children", property); + } + + [Test] + public void TestFindMemberExpressionClass() + { + Expression<Func<Person, object>> e = (Person p) => p.GetType(); + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("class", property); + } + + [Test] + public void TestFindMemberExpressionClassAlias() + { + Person personAlias = null; + Expression<Func<object>> e = () => personAlias.GetType(); + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.class", property); + } + + [Test] + public void TestFindMemberExpressionNullableValue() + { + Expression<Func<Person, object>> e = (Person p) => p.NullableGender.Value; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("NullableGender", property); + } + + [Test] + public void TestFindMemberExpressionNullableValueAlias() + { + Person personAlias = null; + Expression<Func<object>> e = () => personAlias.NullableGender.Value; + string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString(); + Assert.AreEqual("personAlias.NullableGender", property); + } + + [Test] + public void TestFindMemberExpressionConstants() + { + var children = new List<Child> { new Child { Nickname = "test nickname" } }; + Person person = + new Person() + { + Name = "test name", + NullableAge = 4, + Children = children, + }; + + Assert.That(Projection(() => person.Name), Is.EqualTo("test name")); + Assert.That(Projection(() => "test name"), Is.EqualTo("test name")); + Assert.That(Projection(() => person.NullableAge.Value), Is.EqualTo(4)); + Assert.That(Projection(() => person.GetType()), Is.EqualTo(typeof(Person))); + Assert.That(Projection(() => person.Children.First().Nickname), Is.EqualTo("test nickname")); + Assert.That(Projection(() => children[0].Nickname), Is.EqualTo("test nickname")); + } + + private T Projection<T>(Expression<Func<T>> e) + { + var constantProjection = ExpressionProcessor.FindMemberProjection(e.Body); + return (T)typeof(ConstantProjection).GetField("value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(constantProjection); + } + + [Test] public void TestEvaluatePropertyExpression() { string testName = "testName"; Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs 2011-05-25 21:16:01 UTC (rev 5871) @@ -0,0 +1,81 @@ +using System; +using System.Linq.Expressions; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2733 +{ + public interface ISpecification + { + Expression Expression { get; } + } + + public interface ISpecification<T> : ISpecification + { + Expression<Func<T, bool>> Predicate { get; } + } + + public class Specification<T> + { + public Expression<Func<T, bool>> Predicate { get; protected set; } + + public Expression Expression + { + get + { + return Predicate; + } + } + + public Specification(Expression<Func<T, bool>> predicate) + { + Predicate = predicate; + } + } + + [TestFixture] + public class Fixture : BugTestCase + { + Item Item = null; + + protected override void OnSetUp() + { + using (ISession session = Sfi.OpenSession()) + { + var item = new Item(); + session.Persist(item); + session.Flush(); + } + } + + protected override void OnTearDown() + { + using (ISession session = Sfi.OpenSession()) + { + session.CreateQuery("delete from Item").ExecuteUpdate(); + session.Flush(); + } + base.OnTearDown(); + } + + public static Expression<Func<Item, bool>> GetExpression(DateTime startTime) + { + return item => item.Details.StartTime == startTime; + } + + [Test] + public void CanUseExpressionForWhere() + { + using (ISession session = Sfi.OpenSession()) + { + IQueryOver<Item, Item> query = session.QueryOver(() => Item); + + var start = DateTime.UtcNow; + + query + .Where(GetExpression(start)); + + query.List(); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml 2011-05-25 21:16:01 UTC (rev 5871) @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2733" + assembly="NHibernate.Test"> + + <class name="Item" table="`Item_Table`"> + <id name="Id"> + <generator class="native"/> + </id> + <component name="Details"> + <property name="StartTime" /> + </component> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs 2011-05-25 21:16:01 UTC (rev 5871) @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2733 +{ + public class Item + { + public virtual int Id { get; set; } + + public class ItemDetails + { + public virtual DateTime? StartTime { get; set; } + } + + public virtual ItemDetails Details { get; set; } + + public Item() + { + Details = new ItemDetails(); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-25 12:47:06 UTC (rev 5870) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-25 21:16:01 UTC (rev 5871) @@ -854,6 +854,8 @@ <Compile Include="NHSpecificTest\NH2705\SubItemBase.cs" /> <Compile Include="NHSpecificTest\NH2705\SubItemDetails.cs" /> <Compile Include="NHSpecificTest\NH2705\Test.cs" /> + <Compile Include="NHSpecificTest\NH2733\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2733\Model.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> @@ -2696,6 +2698,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2733\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2317\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2366\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2404\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |