diff --git a/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs b/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs index 9025dda..b0312a8 100644 --- a/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs +++ b/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs @@ -170,5 +170,37 @@ namespace PoweredSoft.DynamicLinq.Test var q3b = Persons.AsQueryable().Where(t => t.LastName.Contains("ee") || t.LastName.Contains("ar")); QueryableAssert.AreEqual(q3, q3b); } + + [TestMethod] + public void NotContains() + { + var q1 = Persons.AsQueryable().Query(t => t.Contains("LastName", "ee", negate: true)); + var q1b = Persons.AsQueryable().Where(t => !t.LastName.Contains("ee")); + QueryableAssert.AreEqual(q1, q1b); + } + + [TestMethod] + public void NotContains2() + { + var q1 = Persons.AsQueryable().Query(t => t.NotContains("LastName", "ee")); + var q1b = Persons.AsQueryable().Where(t => !t.LastName.Contains("ee")); + QueryableAssert.AreEqual(q1, q1b); + + var q2 = Persons.AsQueryable().Query(t => t.NotContains("LastName", "ee").AndNotContains("FirstName", "vid")); + var q2b = Persons.AsQueryable().Where(t => !t.LastName.Contains("ee") && !t.FirstName.Contains("vid")); + QueryableAssert.AreEqual(q2, q2b); + + var q3 = Persons.AsQueryable().Query(t => t.NotContains("LastName", "ee").OrNotContains("LastName", "ar")); + var q3b = Persons.AsQueryable().Where(t => !t.LastName.Contains("ee") || !t.LastName.Contains("ar")); + QueryableAssert.AreEqual(q3, q3b); + } + + [TestMethod] + public void ContainsAndNotContains() + { + var q1 = Persons.AsQueryable().Query(t => t.Contains("LastName", "s").AndNotContains("LastName", "r")); + var q1b = Persons.AsQueryable().Where(t => t.LastName.Contains("s") && !t.LastName.Contains("r")); + QueryableAssert.AreEqual(q1, q1b); + } } } diff --git a/PoweredSoft.DynamicLinq.Test/StringComparision.cs b/PoweredSoft.DynamicLinq.Test/StringComparision.cs index a6163a1..aeaf524 100644 --- a/PoweredSoft.DynamicLinq.Test/StringComparision.cs +++ b/PoweredSoft.DynamicLinq.Test/StringComparision.cs @@ -60,6 +60,38 @@ namespace PoweredSoft.DynamicLinq.Test QueryableAssert.AreEqual(a, b, "CaseInsensitive"); } + [TestMethod] + public void NotContains() + { + IQueryable a, b; + + // case sensitive. + a = Persons.AsQueryable().Query(t => t.NotContains("FirstName", "vi", stringComparision: null)); + b = Persons.AsQueryable().Where(t => !t.FirstName.Contains("vi")); + QueryableAssert.AreEqual(a, b, "CaseSensitive"); + + // not case sensitive + a = Persons.AsQueryable().Query(t => t.NotContains("FirstName", "VI", stringComparision: StringComparison.OrdinalIgnoreCase)); + b = Persons.AsQueryable().Where(t => t.FirstName.IndexOf("VI", StringComparison.OrdinalIgnoreCase) == -1); + QueryableAssert.AreEqual(a, b, "CaseInsensitive"); + } + + [TestMethod] + public void NegateNotContains() + { + IQueryable a, b; + + // case sensitive. + a = Persons.AsQueryable().Query(t => t.NotContains("FirstName", "vi", stringComparision: null, negate: true)); + b = Persons.AsQueryable().Where(t => !!t.FirstName.Contains("vi")); + QueryableAssert.AreEqual(a, b, "CaseSensitive"); + + // not case sensitive + a = Persons.AsQueryable().Query(t => t.NotContains("FirstName", "VI", stringComparision: StringComparison.OrdinalIgnoreCase, negate: true)); + b = Persons.AsQueryable().Where(t => !(t.FirstName.IndexOf("VI", StringComparison.OrdinalIgnoreCase) == -1)); + QueryableAssert.AreEqual(a, b, "CaseInsensitive"); + } + [TestMethod] public void StartsWith() { diff --git a/PoweredSoft.DynamicLinq/Constants.cs b/PoweredSoft.DynamicLinq/Constants.cs index 8e5c05e..f2f23ca 100644 --- a/PoweredSoft.DynamicLinq/Constants.cs +++ b/PoweredSoft.DynamicLinq/Constants.cs @@ -16,6 +16,7 @@ namespace PoweredSoft.DynamicLinq LessThan, LessThanOrEqual, Contains, + NotContains, StartsWith, EndsWith, In, diff --git a/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.cs b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.cs index 03738a3..fd24f9f 100644 --- a/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.cs +++ b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.cs @@ -30,7 +30,7 @@ namespace PoweredSoft.DynamicLinq.Fluent public virtual WhereBuilder Compare(string path, ConditionOperators conditionOperators, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, - bool and = true, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) + bool and = true, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) { Filters.Add(new WhereBuilderCondition { @@ -40,7 +40,8 @@ namespace PoweredSoft.DynamicLinq.Fluent Value = value, ConvertStrategy = convertStrategy, CollectionHandling = collectionHandling, - StringComparisation = stringComparision + StringComparisation = stringComparision, + Negate = negate }); return this; @@ -131,7 +132,8 @@ namespace PoweredSoft.DynamicLinq.Fluent filter.CollectionHandling, parameter: parameter, nullChecking: IsNullCheckingEnabled, - stringComparision: filter.StringComparisation + stringComparision: filter.StringComparisation, + negate: filter.Negate ); return ret; diff --git a/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.shortcuts.cs b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.shortcuts.cs index 658f42b..4a04207 100644 --- a/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.shortcuts.cs +++ b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.shortcuts.cs @@ -7,12 +7,12 @@ namespace PoweredSoft.DynamicLinq.Fluent public partial class WhereBuilder { public WhereBuilder And(string path, ConditionOperators conditionOperator, object value, - QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => Compare(path, conditionOperator, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, and: true, stringComparision: stringComparision); + QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Compare(path, conditionOperator, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, and: true, stringComparision: stringComparision, negate: negate); public WhereBuilder Or(string path, ConditionOperators conditionOperator, object value, - QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => Compare(path, conditionOperator, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, and: false, stringComparision: stringComparision); + QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Compare(path, conditionOperator, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, and: false, stringComparision: stringComparision, negate: negate); public WhereBuilder And(Action subQuery) => SubQuery(subQuery, true); @@ -21,25 +21,25 @@ namespace PoweredSoft.DynamicLinq.Fluent => SubQuery(subQuery, false); #region equal - public WhereBuilder Equal(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.Equal, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder Equal(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.Equal, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder AndEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.Equal, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder AndEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.Equal, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder OrEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => Or(path, ConditionOperators.Equal, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder OrEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Or(path, ConditionOperators.Equal, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); #endregion #region not equal - public WhereBuilder NotEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.NotEqual, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder NotEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.NotEqual, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder AndNotEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.NotEqual, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder AndNotEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.NotEqual, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder OrNotEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => Or(path, ConditionOperators.NotEqual, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder OrNotEqual(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Or(path, ConditionOperators.NotEqual, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); #endregion #region GreaterThan @@ -87,36 +87,47 @@ namespace PoweredSoft.DynamicLinq.Fluent #endregion #region contains - public WhereBuilder Contains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.Contains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder Contains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.Contains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder AndContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.Contains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder AndContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.Contains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder OrContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => Or(path, ConditionOperators.Contains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder OrContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Or(path, ConditionOperators.Contains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); + #endregion + + #region not contains + public WhereBuilder NotContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.NotContains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); + + public WhereBuilder AndNotContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.NotContains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); + + public WhereBuilder OrNotContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Or(path, ConditionOperators.NotContains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); #endregion #region starts with - public WhereBuilder StartsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.StartsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder StartsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.StartsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder AndStartsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.StartsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder AndStartsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.StartsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder OrStartsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => Or(path, ConditionOperators.StartsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder OrStartsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Or(path, ConditionOperators.StartsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); #endregion #region ends with - public WhereBuilder EndsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.EndsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder EndsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.EndsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder AndEndsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => And(path, ConditionOperators.EndsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder AndEndsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => And(path, ConditionOperators.EndsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); - public WhereBuilder OrEndsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) - => Or(path, ConditionOperators.EndsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + public WhereBuilder OrEndsWith(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null, bool negate = false) + => Or(path, ConditionOperators.EndsWith, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision, negate: negate); #endregion #region In diff --git a/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilderCondition.cs b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilderCondition.cs index 48ecc3b..272d922 100644 --- a/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilderCondition.cs +++ b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilderCondition.cs @@ -16,5 +16,6 @@ namespace PoweredSoft.DynamicLinq.Fluent public List Conditions { get; set; } = new List(); public QueryCollectionHandling CollectionHandling { get; set; } public StringComparison? StringComparisation { get; set; } = null; + public bool Negate { get; set; } = false; } } diff --git a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs index d9985a6..f64f18d 100644 --- a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs +++ b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs @@ -16,7 +16,7 @@ namespace PoweredSoft.DynamicLinq.Helpers - public static Expression GetConditionExpressionForMember(ParameterExpression parameter, Expression member, ConditionOperators conditionOperator, ConstantExpression constant, StringComparison? stringComparision) + public static Expression GetConditionExpressionForMember(ParameterExpression parameter, Expression member, ConditionOperators conditionOperator, ConstantExpression constant, StringComparison? stringComparision, bool negate) { if (parameter == null) throw new ArgumentNullException("parameter"); @@ -61,6 +61,13 @@ namespace PoweredSoft.DynamicLinq.Helpers else ret = Expression.Call(member, Constants.ContainsMethod, constant); } + else if (conditionOperator == ConditionOperators.NotContains) + { + if (member.Type == stringType && stringComparision.HasValue) + ret = Expression.GreaterThan(Expression.Not(Expression.Call(member, Constants.IndexOfMethod, constant, Expression.Constant(stringComparision.Value))), Expression.Constant(-1)); + else + ret = Expression.Not(Expression.Call(member, Constants.ContainsMethod, constant)); + } else if (conditionOperator == ConditionOperators.StartsWith) { if (member.Type == stringType && stringComparision.HasValue) @@ -78,6 +85,9 @@ namespace PoweredSoft.DynamicLinq.Helpers else throw new ArgumentException("conditionOperator", "Must supply a known condition operator"); + if (negate) + ret = Expression.Not(ret); + return ret; } @@ -436,7 +446,7 @@ namespace PoweredSoft.DynamicLinq.Helpers */ internal static Expression InternalCreateConditionExpression(int recursionStep, Type type, ParameterExpression parameter, Expression current, List parts, - ConditionOperators condition, object value, QueryConvertStrategy convertStrategy, QueryCollectionHandling collectionHandling, bool nullChecking, StringComparison? stringComparison) + ConditionOperators condition, object value, QueryConvertStrategy convertStrategy, QueryCollectionHandling collectionHandling, bool nullChecking, StringComparison? stringComparison, bool negate) { var partStr = parts.First(); var isLast = parts.Count == 1; @@ -460,7 +470,7 @@ namespace PoweredSoft.DynamicLinq.Helpers else { var constant = QueryableHelpers.ResolveConstant(memberExpression, value, convertStrategy); - var filterExpression = QueryableHelpers.GetConditionExpressionForMember(parameter, memberExpression, condition, constant, stringComparison); + var filterExpression = QueryableHelpers.GetConditionExpressionForMember(parameter, memberExpression, condition, constant, stringComparison, negate); var lambda = Expression.Lambda(filterExpression, parameter); return lambda; } @@ -475,7 +485,7 @@ namespace PoweredSoft.DynamicLinq.Helpers { var listGenericArgumentType = memberExpression.Type.GetGenericArguments().First(); var innerParameter = Expression.Parameter(listGenericArgumentType, $"t{++recursionStep}"); - var innerLambda = InternalCreateConditionExpression(recursionStep, listGenericArgumentType, innerParameter, innerParameter, parts.Skip(1).ToList(), condition, value, convertStrategy, collectionHandling, nullChecking, stringComparison); + var innerLambda = InternalCreateConditionExpression(recursionStep, listGenericArgumentType, innerParameter, innerParameter, parts.Skip(1).ToList(), condition, value, convertStrategy, collectionHandling, nullChecking, stringComparison, negate); // the collection method. var collectionMethod = GetCollectionMethod(collectionHandling); @@ -494,14 +504,14 @@ namespace PoweredSoft.DynamicLinq.Helpers { if (nullCheckExpression != null) { - var pathExpr = InternalCreateConditionExpression(recursionStep, type, parameter, memberExpression, parts.Skip(1).ToList(), condition, value, convertStrategy, collectionHandling, nullChecking, stringComparison); + var pathExpr = InternalCreateConditionExpression(recursionStep, type, parameter, memberExpression, parts.Skip(1).ToList(), condition, value, convertStrategy, collectionHandling, nullChecking, stringComparison, negate); var nullCheckResult = Expression.AndAlso(nullCheckExpression, (pathExpr as LambdaExpression).Body); var nullCheckResultLambda = Expression.Lambda((Expression)nullCheckResult, parameter); return nullCheckResultLambda; } - return InternalCreateConditionExpression(recursionStep, type, parameter, memberExpression, parts.Skip(1).ToList(), condition, value, convertStrategy, collectionHandling, nullChecking, stringComparison); + return InternalCreateConditionExpression(recursionStep, type, parameter, memberExpression, parts.Skip(1).ToList(), condition, value, convertStrategy, collectionHandling, nullChecking, stringComparison, negate); } } @@ -560,13 +570,14 @@ namespace PoweredSoft.DynamicLinq.Helpers QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, ParameterExpression parameter = null, bool nullChecking = false, - StringComparison? stringComparision = null) + StringComparison? stringComparision = null, bool negate = false) { var ret = CreateConditionExpression(typeof(T), path, condition, value, convertStrategy, collectionHandling: collectionHandling, parameter: parameter, nullChecking: nullChecking, - stringComparision: stringComparision) as Expression>; + stringComparision: stringComparision, + negate: negate) as Expression>; return ret; } @@ -578,13 +589,14 @@ namespace PoweredSoft.DynamicLinq.Helpers QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, ParameterExpression parameter = null, bool nullChecking = false, - StringComparison? stringComparision = null) + StringComparison? stringComparision = null, + bool negate = false) { if (parameter == null) parameter = Expression.Parameter(type, "t"); var parts = path.Split('.').ToList(); - var result = InternalCreateConditionExpression(1, type, parameter, parameter, parts, condition, value, convertStrategy, collectionHandling, nullChecking, stringComparision); + var result = InternalCreateConditionExpression(1, type, parameter, parameter, parts, condition, value, convertStrategy, collectionHandling, nullChecking, stringComparision, negate); return result; } diff --git a/README.md b/README.md index 10e74be..8d71597 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,8 @@ Assert.AreEqual(first?.FirstName, "David"); > I highly suggest looking @ https://github.com/poweredsoft/dynamicquery if you are interested in this sample. +> Sample how to use DynamicQuery with asp.net mvc core and EF Core: https://github.com/PoweredSoft/DynamicQueryAspNetCoreSample + ```csharp [HttpGet][Route("FindClients")] public IHttpActionResult FindClients(string filterField = null, string filterValue = null,