From: <ric...@us...> - 2010-05-10 11:24:38
|
Revision: 4980 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4980&view=rev Author: ricbrown Date: 2010-05-10 11:24:31 +0000 (Mon, 10 May 2010) Log Message: ----------- Added IResultTransformer method to IQueryOver. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs trunk/nhibernate/src/NHibernate/IQueryOver.cs trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -15,7 +15,7 @@ public QueryOverOrderBuilder(QueryOver<TRoot,TSubType> root, Expression<Func<TSubType, object>> path) : base(root, path) {} - public QueryOverOrderBuilder(QueryOver<TRoot,TSubType> root, Expression<Func<object>> path) : base(root, path) + public QueryOverOrderBuilder(QueryOver<TRoot,TSubType> root, Expression<Func<object>> path, bool isAlias) : base(root, path, isAlias) {} } @@ -26,7 +26,7 @@ public IQueryOverOrderBuilder(IQueryOver<TRoot,TSubType> root, Expression<Func<TSubType, object>> path) : base(root, path) {} - public IQueryOverOrderBuilder(IQueryOver<TRoot,TSubType> root, Expression<Func<object>> path) : base(root, path) + public IQueryOverOrderBuilder(IQueryOver<TRoot,TSubType> root, Expression<Func<object>> path, bool isAlias) : base(root, path, isAlias) {} } @@ -36,24 +36,27 @@ protected TReturn root; protected LambdaExpression path; + protected bool isAlias; protected QueryOverOrderBuilderBase(TReturn root, Expression<Func<TSubType, object>> path) { this.root = root; this.path = path; + this.isAlias = false; } - protected QueryOverOrderBuilderBase(TReturn root, Expression<Func<object>> path) + protected QueryOverOrderBuilderBase(TReturn root, Expression<Func<object>> path, bool isAlias) { this.root = root; this.path = path; + this.isAlias = isAlias; } public TReturn Asc { get { - this.root.UnderlyingCriteria.AddOrder(ExpressionProcessor.ProcessOrder(path, Order.Asc)); + this.root.UnderlyingCriteria.AddOrder(ExpressionProcessor.ProcessOrder(path, Order.Asc, isAlias)); return this.root; } } @@ -62,7 +65,7 @@ { get { - this.root.UnderlyingCriteria.AddOrder(ExpressionProcessor.ProcessOrder(path, Order.Desc)); + this.root.UnderlyingCriteria.AddOrder(ExpressionProcessor.ProcessOrder(path, Order.Desc, isAlias)); return this.root; } } Modified: trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -46,7 +46,7 @@ /// </summary> public QueryOverProjectionBuilder<T> WithAlias(Expression<Func<object>> alias) { - string aliasContainer = ExpressionProcessor.FindMemberExpression(alias.Body); + string aliasContainer = ExpressionProcessor.FindPropertyExpression(alias.Body); lastProjection = Projections.Alias(lastProjection, aliasContainer); return this; } Modified: trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -16,7 +16,7 @@ public static IProjection WithAlias(this IProjection projection, Expression<Func<object>> alias) { - string aliasContainer = ExpressionProcessor.FindMemberExpression(alias.Body); + string aliasContainer = ExpressionProcessor.FindPropertyExpression(alias.Body); return Projections.Alias(projection, aliasContainer); } } Modified: trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -7,6 +7,7 @@ using NHibernate.Engine; using NHibernate.Impl; using NHibernate.SqlCommand; +using NHibernate.Transform; namespace NHibernate.Criterion { @@ -330,9 +331,14 @@ public QueryOverOrderBuilder<TRoot,TSubType> OrderBy(Expression<Func<object>> path) { - return new QueryOverOrderBuilder<TRoot,TSubType>(this, path); + return new QueryOverOrderBuilder<TRoot,TSubType>(this, path, false); } + public QueryOverOrderBuilder<TRoot,TSubType> OrderByAlias(Expression<Func<object>> path) + { + return new QueryOverOrderBuilder<TRoot,TSubType>(this, path, true); + } + public QueryOverOrderBuilder<TRoot,TSubType> ThenBy(Expression<Func<TSubType, object>> path) { return new QueryOverOrderBuilder<TRoot,TSubType>(this, path); @@ -340,15 +346,26 @@ public QueryOverOrderBuilder<TRoot,TSubType> ThenBy(Expression<Func<object>> path) { - return new QueryOverOrderBuilder<TRoot,TSubType>(this, path); + return new QueryOverOrderBuilder<TRoot,TSubType>(this, path, false); } + public QueryOverOrderBuilder<TRoot,TSubType> ThenByAlias(Expression<Func<object>> path) + { + return new QueryOverOrderBuilder<TRoot,TSubType>(this, path, true); + } + public QueryOver<TRoot,TSubType> ClearOrders() { criteria.ClearOrders(); return this; } + public QueryOver<TRoot,TSubType> TransformUsing(IResultTransformer resultTransformer) + { + criteria.SetResultTransformer(resultTransformer); + return this; + } + public QueryOver<TRoot,TSubType> Skip(int firstResult) { criteria.SetFirstResult(firstResult); @@ -671,17 +688,26 @@ { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path); } IQueryOverOrderBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.OrderBy(Expression<Func<object>> path) - { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path); } + { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path, false); } + IQueryOverOrderBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.OrderByAlias(Expression<Func<object>> path) + { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path, true); } + IQueryOverOrderBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.ThenBy(Expression<Func<TSubType, object>> path) { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path); } IQueryOverOrderBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.ThenBy(Expression<Func<object>> path) - { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path); } + { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path, false); } + IQueryOverOrderBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.ThenByAlias(Expression<Func<object>> path) + { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path, true); } + IQueryOver<TRoot,TSubType> IQueryOver<TRoot, TSubType>.ClearOrders() { return ClearOrders(); } + IQueryOver<TRoot,TSubType> IQueryOver<TRoot,TSubType>.TransformUsing(IResultTransformer resultTransformer) + { return TransformUsing(resultTransformer); } + IQueryOver<TRoot,TSubType> IQueryOver<TRoot,TSubType>.Skip(int firstResult) { return Skip(firstResult); } Modified: trunk/nhibernate/src/NHibernate/IQueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQueryOver.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate/IQueryOver.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -6,6 +6,7 @@ using NHibernate.Criterion; using NHibernate.Criterion.Lambda; using NHibernate.SqlCommand; +using NHibernate.Transform; namespace NHibernate { @@ -262,6 +263,13 @@ IQueryOverOrderBuilder<TRoot,TSubType> OrderBy(Expression<Func<object>> path); /// <summary> + /// Add order for an aliased projection expressed as a lambda expression + /// </summary> + /// <param name="path">Lambda expression</param> + /// <returns>criteria instance</returns> + IQueryOverOrderBuilder<TRoot,TSubType> OrderByAlias(Expression<Func<object>> path); + + /// <summary> /// Add order expressed as a lambda expression /// </summary> /// <param name="path">Lambda expression</param> @@ -276,11 +284,23 @@ IQueryOverOrderBuilder<TRoot,TSubType> ThenBy(Expression<Func<object>> path); /// <summary> + /// Add order for an aliased projection expressed as a lambda expression + /// </summary> + /// <param name="path">Lambda expression</param> + /// <returns>criteria instance</returns> + IQueryOverOrderBuilder<TRoot,TSubType> ThenByAlias(Expression<Func<object>> path); + + /// <summary> /// Clear all orders from the query. /// </summary> IQueryOver<TRoot, TSubType> ClearOrders(); /// <summary> + /// Transform the results using the supplied IResultTransformer + /// </summary> + IQueryOver<TRoot,TSubType> TransformUsing(IResultTransformer resultTransformer); + + /// <summary> /// Set the first result to be retrieved /// </summary> /// <param name="firstResult"></param> Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -174,6 +174,17 @@ } /// <summary> + /// Retrieves the name of the property from a member expression (without leading member access) + /// </summary> + public static string FindPropertyExpression(Expression expression) + { + string memberExpression = FindMemberExpression(expression); + int periodPosition = memberExpression.LastIndexOf('.') + 1; + string property = (periodPosition <= 0) ? memberExpression : memberExpression.Substring(periodPosition); + return property; + } + + /// <summary> /// Retrieves a detached criteria from an appropriate lambda expression /// </summary> /// <param name="expression">Expresson for detached criteria using .As<>() extension"/></param> @@ -458,11 +469,13 @@ /// </summary> /// <param name="expression">The lambda expression to convert</param> /// <param name="orderDelegate">The appropriate order delegate (order direction)</param> + /// <param name="isAlias">Indicates if the path is an aliased projection</param> /// <returns>NHibernate Order</returns> public static Order ProcessOrder( LambdaExpression expression, - Func<string, Order> orderDelegate) + Func<string, Order> orderDelegate, + bool isAlias) { - string property = FindMemberExpression(expression.Body); + string property = isAlias ? FindPropertyExpression(expression.Body) : FindMemberExpression(expression.Body); Order order = orderDelegate(property); return order; } Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -146,6 +146,38 @@ } [Test] + public void Project_TransformToDto() + { + using (ISession s = OpenSession()) + using (ITransaction t = s.BeginTransaction()) + { + s.Save(new Person() { Name = "test person 1", Age = 20 }); + s.Save(new Person() { Name = "test person 1", Age = 30 }); + s.Save(new Person() { Name = "test person 2", Age = 40 }); + t.Commit(); + } + + using (ISession s = OpenSession()) + { + PersonSummary summary = null; + var actual = + s.QueryOver<Person>() + .Select(list => list + .SelectGroup(p => p.Name).WithAlias(() => summary.Name) + .Select(Projections.RowCount()).WithAlias(() => summary.Count)) + .OrderByAlias(() => summary.Name).Asc + .TransformUsing(Transformers.AliasToBean<PersonSummary>()) + .List<PersonSummary>(); + + Assert.That(actual.Count, Is.EqualTo(2)); + Assert.That(actual[0].Name, Is.EqualTo("test person 1")); + Assert.That(actual[0].Count, Is.EqualTo(2)); + Assert.That(actual[1].Name, Is.EqualTo("test person 2")); + Assert.That(actual[1].Count, Is.EqualTo(1)); + } + } + + [Test] public void UniqueResult() { using (ISession s = OpenSession()) @@ -244,7 +276,7 @@ .Select(list => list .Select(p => p.Name) .SelectSubQuery(childCountQuery).WithAlias(() => childCountAlias)) - .OrderBy(() => childCountAlias).Desc + .OrderByAlias(() => childCountAlias).Desc .List<object[]>() .Select(props => new { Name = (string)props[0], Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -157,6 +157,13 @@ return; } + if (expected is ConstructorInfo) + { + Assert.AreEqual(expected.ToString(), actual.ToString()); + _fieldPath.Pop(); + return; + } + while (expectedType != null) { foreach (FieldInfo fieldInfo in expectedType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -75,5 +75,11 @@ } + public class PersonSummary + { + public string Name { get; set; } + public int Count { get; set; } + } + } Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -41,7 +41,7 @@ .SetProjection(Projections.ProjectionList() .Add(Projections.Alias(Projections.Avg("Age"), "personAgeProjectionAlias")) .Add(Projections.Avg("Age"), "personAgeProjectionAlias") - .Add(Projections.Avg("personAlias.Age")) + .Add(Projections.Avg("personAlias.Age"), "Age") .Add(Projections.Count("Age")) .Add(Projections.Count("personAlias.Age")) .Add(Projections.CountDistinct("Age")) @@ -65,7 +65,7 @@ .Select(Projections.ProjectionList() .Add(Projections.Avg<Person>(p => p.Age).WithAlias(() => personAgeProjectionAlias)) .Add(Projections.Avg<Person>(p => p.Age), () => personAgeProjectionAlias) - .Add(Projections.Avg(() => personAlias.Age)) + .Add(Projections.Avg(() => personAlias.Age).WithAlias(() => personAlias.Age)) .Add(Projections.Count<Person>(p => p.Age)) .Add(Projections.Count(() => personAlias.Age)) .Add(Projections.CountDistinct<Person>(p => p.Age)) @@ -93,7 +93,7 @@ .SetProjection(Projections.ProjectionList() .Add(Projections.Alias(Projections.Avg("Age"), "personAgeProjectionAlias")) .Add(Projections.Avg("Age")) - .Add(Projections.Avg("personAlias.Age")) + .Add(Projections.Avg("personAlias.Age"), "Age") .Add(Projections.Count("Age")) .Add(Projections.Count("personAlias.Age")) .Add(Projections.CountDistinct("Age")) @@ -117,7 +117,7 @@ .Select(list => list .SelectAvg(p => p.Age).WithAlias(() => personAgeProjectionAlias) .Select(Projections.Avg("Age")) // allows private properties - .SelectAvg(() => personAlias.Age) + .SelectAvg(() => personAlias.Age).WithAlias(() => personAlias.Age) .SelectCount(p => p.Age) .SelectCount(() => personAlias.Age) .SelectCountDistinct(p => p.Age) Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2010-05-07 22:44:13 UTC (rev 4979) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2010-05-10 11:24:31 UTC (rev 4980) @@ -354,15 +354,20 @@ .AddOrder(Order.Asc("Name")) .AddOrder(Order.Desc("Age")) .AddOrder(Order.Desc("personAlias.Name")) - .AddOrder(Order.Asc("personAlias.Age")); + .AddOrder(Order.Asc("personAlias.Age")) + .AddOrder(Order.Asc("summary")) + .AddOrder(Order.Desc("Count")); Person personAlias = null; + PersonSummary summary = null; IQueryOver<Person> actual = CreateTestQueryOver<Person>(() => personAlias) .OrderBy(p => p.Name).Asc .ThenBy(p => p.Age).Desc .ThenBy(() => personAlias.Name).Desc - .ThenBy(() => personAlias.Age).Asc; + .ThenBy(() => personAlias.Age).Asc + .OrderByAlias(() => summary).Asc + .ThenByAlias(() => summary.Count).Desc; AssertCriteriaAreEqual(expected, actual); } @@ -454,6 +459,20 @@ } [Test] + public void ResultTransformer() + { + ICriteria expected = + CreateTestCriteria(typeof(Person)) + .SetResultTransformer(Transformers.AliasToBean<Person>()); + + IQueryOver<Person> actual = + CreateTestQueryOver<Person>() + .TransformUsing(Transformers.AliasToBean<Person>()); + + AssertCriteriaAreEqual(expected, actual); + } + + [Test] public void LockAlias() { ICriteria expected = This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |