diff --git a/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs b/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs index 730c2c9..6df24b4 100644 --- a/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs +++ b/PoweredSoft.DynamicLinq.Test/ShortcutTests.cs @@ -178,5 +178,29 @@ namespace PoweredSoft.DynamicLinq.Test var q1b = Persons.AsQueryable().Where(t => !t.LastName.Contains("ee")); QueryableAssert.AreEqual(q1, q1b); } + + [TestMethod] + public void NotContains() + { + 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..431d054 100644 --- a/PoweredSoft.DynamicLinq.Test/StringComparision.cs +++ b/PoweredSoft.DynamicLinq.Test/StringComparision.cs @@ -60,6 +60,22 @@ 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 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.shortcuts.cs b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.shortcuts.cs index 028f670..a1439a6 100644 --- a/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.shortcuts.cs +++ b/PoweredSoft.DynamicLinq/Fluent/Where/WhereBuilder.shortcuts.cs @@ -97,6 +97,17 @@ namespace PoweredSoft.DynamicLinq.Fluent => 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) + => And(path, ConditionOperators.NotContains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + + public WhereBuilder AndNotContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) + => And(path, ConditionOperators.NotContains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + + public WhereBuilder OrNotContains(string path, object value, QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null) + => Or(path, ConditionOperators.NotContains, value, convertStrategy: convertStrategy, collectionHandling: collectionHandling, stringComparision: stringComparision); + #endregion + #region starts with 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); diff --git a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs index 418655e..f64f18d 100644 --- a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs +++ b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs @@ -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) 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,