From: <ric...@us...> - 2009-11-19 16:04:51
|
Revision: 4839 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4839&view=rev Author: ricbrown Date: 2009-11-19 16:04:43 +0000 (Thu, 19 Nov 2009) Log Message: ----------- Added typed inline restrictions to QueryOver. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs trunk/nhibernate/src/NHibernate/IQueryOver.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs Added: trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs 2009-11-19 16:04:43 UTC (rev 4839) @@ -0,0 +1,169 @@ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq.Expressions; + +using NHibernate.Impl; +using NHibernate.SqlCommand; + +namespace NHibernate.Criterion.Lambda +{ + + public class QueryOverRestrictionBuilder<T> : QueryOverRestrictionBuilderBase<QueryOver<T>, T> + { + + public QueryOverRestrictionBuilder(QueryOver<T> root, string propertyName) + : base(root, propertyName) { } + + } + + public class IQueryOverRestrictionBuilder<T> : QueryOverRestrictionBuilderBase<IQueryOver<T>, T> + { + + public IQueryOverRestrictionBuilder(IQueryOver<T> root, string propertyName) + : base(root, propertyName) { } + + } + + public class QueryOverRestrictionBuilderBase<R, T> + where R : IQueryOver<T> + { + public class LambdaBetweenBuilder + { + private R root; + private string propertyName; + private object lo; + + public LambdaBetweenBuilder(R root, string propertyName, object lo) + { + this.root = root; + this.propertyName = propertyName; + this.lo = lo; + } + + public R And(object hi) + { + return (R)root.And(Restrictions.Between(propertyName, lo, hi)); + } + } + + private R root; + private string propertyName; + + /// <summary> + /// Constructed with property name + /// </summary> + public QueryOverRestrictionBuilderBase(R root, string propertyName) + { + this.root = root; + this.propertyName = propertyName; + } + + /// <summary> + /// Apply a "between" constraint to the named property + /// </summary> + public LambdaBetweenBuilder IsBetween(object lo) + { + return new LambdaBetweenBuilder(root, propertyName, lo); + } + + /// <summary> + /// Apply an "in" constraint to the named property + /// </summary> + public R IsIn(ICollection values) + { + return (R)root.And(Restrictions.In(propertyName, values)); + } + + /// <summary> + /// Apply an "in" constraint to the named property + /// </summary> + public R IsIn(object[] values) + { + return (R)root.And(Restrictions.In(propertyName, values)); + } + + /// <summary> + /// Apply an "in" constraint to the named property + /// </summary> + public R IsInG<T>(ICollection<T> values) + { + return (R)root.And(Restrictions.InG(propertyName, values)); + } + + /// <summary> + /// A case-insensitive "like", similar to Postgres "ilike" operator + /// </summary> + public R IsInsensitiveLike(object value) + { + return (R)root.And(Restrictions.InsensitiveLike(propertyName, value)); + } + + /// <summary> + /// A case-insensitive "like", similar to Postgres "ilike" operator + /// </summary> + public R IsInsensitiveLike(string value, MatchMode matchMode) + { + return (R)root.And(Restrictions.InsensitiveLike(propertyName, value, matchMode)); + } + + /// <summary> + /// Apply an "is empty" constraint to the named property + /// </summary> + public R IsEmpty + { + get { return (R)root.And(Restrictions.IsEmpty(propertyName)); } + } + + /// <summary> + /// Apply a "not is empty" constraint to the named property + /// </summary> + public R IsNotEmpty + { + get { return (R)root.And(Restrictions.IsNotEmpty(propertyName)); } + } + + /// <summary> + /// Apply an "is null" constraint to the named property + /// </summary> + public R IsNull + { + get { return (R)root.And(Restrictions.IsNull(propertyName)); } + } + + /// <summary> + /// Apply an "not is null" constraint to the named property + /// </summary> + public R IsNotNull + { + get { return (R)root.And(Restrictions.IsNotNull(propertyName)); } + } + + /// <summary> + /// Apply a "like" constraint to the named property + /// </summary> + public R IsLike(object value) + { + return (R)root.And(Restrictions.Like(propertyName, value)); + } + + /// <summary> + /// Apply a "like" constraint to the named property + /// </summary> + public R IsLike(string value, MatchMode matchMode) + { + return (R)root.And(Restrictions.Like(propertyName, value, matchMode)); + } + + /// <summary> + /// Apply a "like" constraint to the named property + /// </summary> + public R IsLike(string value, MatchMode matchMode, char? escapeChar) + { + return (R)root.And(Restrictions.Like(propertyName, value, matchMode, escapeChar)); + } + + } + +} Modified: trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2009-11-19 14:46:12 UTC (rev 4838) +++ trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2009-11-19 16:04:43 UTC (rev 4839) @@ -89,6 +89,16 @@ return Add(expression); } + public QueryOverRestrictionBuilder<T> AndRestrictionOn(Expression<Func<T, object>> expression) + { + return new QueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); + } + + public QueryOverRestrictionBuilder<T> AndRestrictionOn(Expression<Func<object>> expression) + { + return new QueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); + } + public QueryOver<T> Where(Expression<Func<T, bool>> expression) { return Add(expression); @@ -104,6 +114,16 @@ return Add(expression); } + public QueryOverRestrictionBuilder<T> WhereRestrictionOn(Expression<Func<T, object>> expression) + { + return new QueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); + } + + public QueryOverRestrictionBuilder<T> WhereRestrictionOn(Expression<Func<object>> expression) + { + return new QueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); + } + public QueryOver<T> Select(params Expression<Func<T, object>>[] projections) { List<IProjection> projectionList = new List<IProjection>(); @@ -457,6 +477,12 @@ IQueryOver<T> IQueryOver<T>.And(ICriterion expression) { return And(expression); } + IQueryOverRestrictionBuilder<T> IQueryOver<T>.AndRestrictionOn(Expression<Func<T, object>> expression) + { return new IQueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); } + + IQueryOverRestrictionBuilder<T> IQueryOver<T>.AndRestrictionOn(Expression<Func<object>> expression) + { return new IQueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); } + IQueryOver<T> IQueryOver<T>.Where(Expression<Func<T, bool>> expression) { return Where(expression); } @@ -466,6 +492,12 @@ IQueryOver<T> IQueryOver<T>.Where(ICriterion expression) { return Where(expression); } + IQueryOverRestrictionBuilder<T> IQueryOver<T>.WhereRestrictionOn(Expression<Func<T, object>> expression) + { return new IQueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); } + + IQueryOverRestrictionBuilder<T> IQueryOver<T>.WhereRestrictionOn(Expression<Func<object>> expression) + { return new IQueryOverRestrictionBuilder<T>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); } + IQueryOver<T> IQueryOver<T>.Select(params Expression<Func<T, object>>[] projections) { return Select(projections); } Modified: trunk/nhibernate/src/NHibernate/IQueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQueryOver.cs 2009-11-19 14:46:12 UTC (rev 4838) +++ trunk/nhibernate/src/NHibernate/IQueryOver.cs 2009-11-19 16:04:43 UTC (rev 4839) @@ -50,6 +50,20 @@ IQueryOver<T> And(ICriterion expression); /// <summary> + /// Add restriction to a property + /// </summary> + /// <param name="expression">Lambda expression containing path to property</param> + /// <returns>criteria instance</returns> + IQueryOverRestrictionBuilder<T> AndRestrictionOn(Expression<Func<T, object>> expression); + + /// <summary> + /// Add restriction to a property + /// </summary> + /// <param name="expression">Lambda expression containing path to property</param> + /// <returns>criteria instance</returns> + IQueryOverRestrictionBuilder<T> AndRestrictionOn(Expression<Func<object>> expression); + + /// <summary> /// Identical semantics to Add() to allow more readable queries /// </summary> /// <param name="expression">Lambda expression</param> @@ -69,6 +83,20 @@ IQueryOver<T> Where(ICriterion expression); /// <summary> + /// Identical semantics to AndRestrictionOn() to allow more readable queries + /// </summary> + /// <param name="expression">Lambda expression</param> + /// <returns>criteria instance</returns> + IQueryOverRestrictionBuilder<T> WhereRestrictionOn(Expression<Func<T, object>> expression); + + /// <summary> + /// Identical semantics to AndRestrictionOn() to allow more readable queries + /// </summary> + /// <param name="expression">Lambda expression</param> + /// <returns>criteria instance</returns> + IQueryOverRestrictionBuilder<T> WhereRestrictionOn(Expression<Func<object>> expression); + + /// <summary> /// Add projection expressed as a lambda expression /// </summary> /// <param name="projections">Lambda expressions</param> Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-11-19 14:46:12 UTC (rev 4838) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-11-19 16:04:43 UTC (rev 4839) @@ -512,6 +512,7 @@ <Compile Include="Criterion\Lambda\QueryOverJoinBuilder.cs" /> <Compile Include="Criterion\Lambda\QueryOverLockBuilder.cs" /> <Compile Include="Criterion\Lambda\QueryOverOrderBuilder.cs" /> + <Compile Include="Criterion\Lambda\QueryOverRestrictionBuilder.cs" /> <Compile Include="Criterion\Lambda\QueryOverSubqueryBuilder.cs" /> <Compile Include="Criterion\Lambda\QueryOverSubqueryPropertyBuilder.cs" /> <Compile Include="Dialect\MsSql2008Dialect.cs" /> Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs 2009-11-19 14:46:12 UTC (rev 4838) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs 2009-11-19 16:04:43 UTC (rev 4839) @@ -105,6 +105,68 @@ AssertCriteriaAreEqual(expected, actual); } + [Test] + public void SqlOperatorsInline() + { + ICriteria expected = + CreateTestCriteria(typeof(Person), "personAlias") + .Add(Restrictions.Between("Age", 18, 65)) + .Add(Restrictions.Between("personAlias.Age", 18, 65)) + .Add(Restrictions.In("Name", new string[] { "name1", "name2", "name3" })) + .Add(Restrictions.In("personAlias.Name", new ArrayList() { "name1", "name2", "name3" })) + .Add(Restrictions.InG<int>("Age", new int[] { 1, 2, 3 })) + .Add(Restrictions.InsensitiveLike("Name", "test")) + .Add(Restrictions.InsensitiveLike("Name", "tEsT", MatchMode.Anywhere)) + .Add(Restrictions.IsEmpty("Children")) + .Add(Restrictions.IsNotEmpty("Children")) + .Add(Restrictions.IsNotNull("Name")) + .Add(Restrictions.IsNull("Name")) + .Add(Restrictions.Like("Name", "%test%")) + .Add(Restrictions.Like("Name", "test", MatchMode.Anywhere)) + .Add(Restrictions.Like("Name", "test", MatchMode.Anywhere, '?')); + + Person personAlias = null; + var actual = + CreateTestQueryOver<Person>(() => personAlias) + .WhereRestrictionOn(p => p.Age).IsBetween(18).And(65) + .WhereRestrictionOn(() => personAlias.Age).IsBetween(18).And(65) + .AndRestrictionOn(p => p.Name).IsIn(new string[] { "name1", "name2", "name3" }) + .AndRestrictionOn(() => personAlias.Name).IsIn(new ArrayList() { "name1", "name2", "name3" }) + .AndRestrictionOn(p => p.Age).IsInG<int>(new int[] { 1, 2, 3 }) + .AndRestrictionOn(p => p.Name).IsInsensitiveLike("test") + .AndRestrictionOn(p => p.Name).IsInsensitiveLike("tEsT", MatchMode.Anywhere) + .AndRestrictionOn(p => p.Children).IsEmpty + .AndRestrictionOn(p => p.Children).IsNotEmpty + .AndRestrictionOn(p => p.Name).IsNotNull + .AndRestrictionOn(p => p.Name).IsNull + .AndRestrictionOn(p => p.Name).IsLike("%test%") + .AndRestrictionOn(p => p.Name).IsLike("test", MatchMode.Anywhere) + .AndRestrictionOn(p => p.Name).IsLike("test", MatchMode.Anywhere, '?'); + + AssertCriteriaAreEqual(expected, actual); + } + + [Test] + public void DetachedRestrictions() + { + DetachedCriteria expected = + DetachedCriteria.For<Person>("personAlias") + .Add(Restrictions.Between("Age", 18, 65)) + .Add(Restrictions.Between("personAlias.Age", 18, 65)) + .Add(Restrictions.In("Name", new string[] { "name1", "name2", "name3" })) + .Add(Restrictions.In("personAlias.Name", new ArrayList() { "name1", "name2", "name3" })); + + Person personAlias = null; + QueryOver<Person> actual = + new QueryOver<Person>(() => personAlias) + .WhereRestrictionOn(p => p.Age).IsBetween(18).And(65) + .WhereRestrictionOn(() => personAlias.Age).IsBetween(18).And(65) + .AndRestrictionOn(p => p.Name).IsIn(new string[] { "name1", "name2", "name3" }) + .AndRestrictionOn(() => personAlias.Name).IsIn(new ArrayList() { "name1", "name2", "name3" }); + + AssertCriteriaAreEqual(expected, actual); + } + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |