From 3ad9c3b14422d2242365114aa311e73515e588af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Mon, 15 May 2017 23:11:49 +0200 Subject: [PATCH 1/7] Update DynamicQueryableExtensions.cs So a cached LambdaExpression could be used --- .../DynamicQueryableExtensions.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs index 5ac59745..808d5ee8 100644 --- a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs +++ b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs @@ -1314,6 +1314,20 @@ public static IQueryable Where([NotNull] this IQueryable source, [NotNull] strin var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "Where", new[] { source.ElementType }, source.Expression, Expression.Quote(lambda))); return source.Provider.CreateQuery(optimized); } + + /// + /// Filters a sequence of values based on a predicate. + /// + /// A to filter. + /// A cached Lambda Expression. + public static IQueryable Where(this IQueryable source, LambdaExpression lambda) + { + Check.NotNull(source, nameof(source)); + Check.NotNull(lambda, nameof(lambda)); + + var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "Where", new[] { source.ElementType }, source.Expression, Expression.Quote(lambda))); + return source.Provider.CreateQuery(optimized); + } #endregion #region Private Helpers From c6836eb5ec91ebdcc0179e0e9b0e8e98aee10086 Mon Sep 17 00:00:00 2001 From: jogibear9988 Date: Tue, 16 May 2017 00:33:11 +0200 Subject: [PATCH 2/7] Test where with cached Lambda --- .../ExpressionTests.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs index 89e702fb..40d5c12c 100644 --- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs +++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs @@ -1205,5 +1205,22 @@ public void ExpressionTests_Where_DoubleDecimalCompare() Assert.Equal(expected, result); } + + [Fact] + public void ExpressionTests_Where_WithCachedLambda() + { + var list = new List + { + new SimpleValuesModel { IntValue = 1 }, + new SimpleValuesModel { IntValue = 3 }, + new SimpleValuesModel { IntValue = 2 }, + new SimpleValuesModel { IntValue = 3 } + }; + + var lambda = DynamicExpressionParser.ParseLambda(typeof(SimpleValuesModel), typeof(bool), "IntValue == 3"); + var res = DynamicQueryableExtensions.Where(list.AsQueryable(), lambda); + + Assert.Equal(res.Count(), 2); + } } } \ No newline at end of file From 0d7d596c9b1ac1d410eae2a68d449f3db2dda738 Mon Sep 17 00:00:00 2001 From: jogibear9988 Date: Tue, 16 May 2017 00:39:11 +0200 Subject: [PATCH 3/7] allow cached lambdas also in count & any --- .../DynamicQueryableExtensions.cs | 30 ++++++++++++++++++- .../ExpressionTests.cs | 7 ++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs index 808d5ee8..aa701ea6 100644 --- a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs +++ b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs @@ -96,6 +96,20 @@ public static bool Any([NotNull] this IQueryable source, [NotNull] string predic return Execute(_anyPredicate, source, lambda); } + + /// + /// Determines whether a sequence contains any elements. + /// + /// A sequence to check for being empty. + /// A cached Lambda Expression. + /// true if the source sequence contains any elements; otherwise, false. + public static bool Any([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) + { + Check.NotNull(source, nameof(source)); + Check.NotNull(lambda, nameof(lambda)); + + return Execute(_anyPredicate, source, lambda); + } #endregion Any #region AsEnumerable @@ -170,6 +184,20 @@ public static int Count([NotNull] this IQueryable source, [NotNull] string predi return Execute(_countPredicate, source, lambda); } + + /// + /// Returns the number of elements in a sequence. + /// + /// The that contains the elements to be counted. + /// A cached Lambda Expression. + /// The number of elements in the specified sequence that satisfies a condition. + public static int Count([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) + { + Check.NotNull(source, nameof(source)); + Check.NotNull(lambda, nameof(lambda)); + + return Execute(_countPredicate, source, lambda); + } #endregion Count #region Distinct @@ -1320,7 +1348,7 @@ public static IQueryable Where([NotNull] this IQueryable source, [NotNull] strin /// /// A to filter. /// A cached Lambda Expression. - public static IQueryable Where(this IQueryable source, LambdaExpression lambda) + public static IQueryable Where([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) { Check.NotNull(source, nameof(source)); Check.NotNull(lambda, nameof(lambda)); diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs index 40d5c12c..7a76c1a7 100644 --- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs +++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs @@ -1219,8 +1219,13 @@ public void ExpressionTests_Where_WithCachedLambda() var lambda = DynamicExpressionParser.ParseLambda(typeof(SimpleValuesModel), typeof(bool), "IntValue == 3"); var res = DynamicQueryableExtensions.Where(list.AsQueryable(), lambda); - Assert.Equal(res.Count(), 2); + + var res2 = DynamicQueryableExtensions.Any(list.AsQueryable(), lambda); + Assert.True(res2); + + var res3 = DynamicQueryableExtensions.Count(list.AsQueryable(), lambda); + Assert.Equal(res3, 2); } } } \ No newline at end of file From 51de0883795c9bba04fc1c7a077c193559cf3d8d Mon Sep 17 00:00:00 2001 From: jogibear9988 Date: Tue, 16 May 2017 09:18:15 +0200 Subject: [PATCH 4/7] Support also First,FirstOrDefault,Single,... --- .../DynamicQueryableExtensions.cs | 197 ++++++++++++++++++ .../ExpressionTests.cs | 18 ++ 2 files changed, 215 insertions(+) diff --git a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs index aa701ea6..df74787a 100644 --- a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs +++ b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs @@ -266,6 +266,22 @@ public static dynamic First([NotNull] this IQueryable source, [NotNull] string p return Execute(_firstPredicate, source, lambda); } + + /// + /// Returns the first element of a sequence that satisfies a specified condition. + /// + /// The to return the first element of. + /// A cached Lambda Expression. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object First([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#else + public static dynamic First([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#endif + { + Check.NotNull(source, nameof(source)); + return Execute(_firstPredicate, source, lambda); + } #endregion First #region FirstOrDefault @@ -307,6 +323,23 @@ public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull] return Execute(_firstOrDefaultPredicate, source, lambda); } + + /// + /// Returns the first element of a sequence that satisfies a specified condition or a default value if no such element is found. + /// + /// The to return the first element of. + /// A cached Lambda Expression. + /// default if source is empty or if no element passes the test specified by predicate; otherwise, the first element in source that passes the test specified by predicate. +#if NET35 + public static object FirstOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#else + public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#endif + { + Check.NotNull(source, nameof(source)); + + return Execute(_firstOrDefaultPredicate, source, lambda); + } private static readonly MethodInfo _firstOrDefaultPredicate = GetMethod(nameof(Queryable.FirstOrDefault), 1); #endregion FirstOrDefault @@ -591,6 +624,46 @@ public static dynamic Last([NotNull] this IQueryable source) return Execute(_last, source); } + + private static readonly MethodInfo _lastPredicate = GetMethod(nameof(Queryable.Last), 1); + + /// + /// Returns the last element of a sequence that satisfies a specified condition. + /// + /// The to return the last element of. + /// A function to test each element for a condition. + /// An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object Last([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#else + public static dynamic Last([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#endif + { + Check.NotNull(source, nameof(source)); + Check.NotEmpty(predicate, nameof(predicate)); + + bool createParameterCtor = source.IsLinqToObjects(); + LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null, predicate, args); + + return Execute(_lastPredicate, source, lambda); + } + + /// + /// Returns the last element of a sequence that satisfies a specified condition. + /// + /// The to return the last element of. + /// A cached Lambda Expression. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object Last([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#else + public static dynamic Last([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#endif + { + Check.NotNull(source, nameof(source)); + return Execute(_lastPredicate, source, lambda); + } #endregion Last #region LastOrDefault @@ -610,6 +683,46 @@ public static dynamic LastOrDefault([NotNull] this IQueryable source) return Execute(_lastDefault, source); } + + private static readonly MethodInfo _lastDefaultPredicate = GetMethod(nameof(Queryable.LastOrDefault), 1); + + /// + /// Returns the last element of a sequence that satisfies a specified condition, or a default value if the sequence contains no elements. + /// + /// The to return the last element of. + /// A function to test each element for a condition. + /// An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object LastOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#else + public static dynamic LastOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#endif + { + Check.NotNull(source, nameof(source)); + Check.NotEmpty(predicate, nameof(predicate)); + + bool createParameterCtor = source.IsLinqToObjects(); + LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null, predicate, args); + + return Execute(_lastDefaultPredicate, source, lambda); + } + + /// + /// Returns the last element of a sequence that satisfies a specified condition, or a default value if the sequence contains no elements. + /// + /// The to return the last element of. + /// A cached Lambda Expression. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object LastOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#else + public static dynamic LastOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#endif + { + Check.NotNull(source, nameof(source)); + return Execute(_lastDefaultPredicate, source, lambda); + } #endregion LastOrDefault #region OrderBy @@ -1094,6 +1207,48 @@ public static dynamic Single([NotNull] this IQueryable source) return source.Provider.Execute(optimized); } + private static readonly MethodInfo _singlePredicate = GetMethod(nameof(Queryable.Single), 1); + + /// + /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if there + /// is not exactly one element in the sequence. + /// + /// The to return the last element of. + /// A function to test each element for a condition. + /// An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object Single([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#else + public static dynamic Single([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#endif + { + Check.NotNull(source, nameof(source)); + Check.NotEmpty(predicate, nameof(predicate)); + + bool createParameterCtor = source.IsLinqToObjects(); + LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null, predicate, args); + + return Execute(_singlePredicate, source, lambda); + } + + /// + /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if there + /// is not exactly one element in the sequence. + /// + /// The to return the last element of. + /// A cached Lambda Expression. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object Single([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#else + public static dynamic Single([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#endif + { + Check.NotNull(source, nameof(source)); + return Execute(_singlePredicate, source, lambda); + } + /// /// Returns the only element of a sequence, or a default value if the sequence /// is empty; this method throws an exception if there is more than one element @@ -1112,6 +1267,48 @@ public static dynamic SingleOrDefault([NotNull] this IQueryable source) var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "SingleOrDefault", new[] { source.ElementType }, source.Expression)); return source.Provider.Execute(optimized); } + + private static readonly MethodInfo _singleDefaultPredicate = GetMethod(nameof(Queryable.SingleOrDefault), 1); + + /// + /// Returns the only element of a sequence that satisfies a specified condition or a default value if the sequence + /// is empty; and throws an exception if there is not exactly one element in the sequence. + /// + /// The to return the last element of. + /// A function to test each element for a condition. + /// An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object SingleOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#else + public static dynamic SingleOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args) +#endif + { + Check.NotNull(source, nameof(source)); + Check.NotEmpty(predicate, nameof(predicate)); + + bool createParameterCtor = source.IsLinqToObjects(); + LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null, predicate, args); + + return Execute(_singleDefaultPredicate, source, lambda); + } + + /// + /// Returns the only element of a sequence that satisfies a specified condition or a default value if the sequence + /// is empty; and throws an exception if there is not exactly one element in the sequence. + /// + /// The to return the last element of. + /// A cached Lambda Expression. + /// The first element in source that passes the test in predicate. +#if NET35 + public static object SingleOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#else + public static dynamic SingleOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda) +#endif + { + Check.NotNull(source, nameof(source)); + return Execute(_singleDefaultPredicate, source, lambda); + } #endregion Single/SingleOrDefault #region Skip diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs index 7a76c1a7..224f327a 100644 --- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs +++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs @@ -1226,6 +1226,24 @@ public void ExpressionTests_Where_WithCachedLambda() var res3 = DynamicQueryableExtensions.Count(list.AsQueryable(), lambda); Assert.Equal(res3, 2); + + var res4 = DynamicQueryableExtensions.First(list.AsQueryable(), lambda); + Assert.Equal(res4, list[1]); + + var res5 = DynamicQueryableExtensions.FirstOrDefault(list.AsQueryable(), lambda); + Assert.Equal(res5, list[1]); + + var res6 = DynamicQueryableExtensions.Last(list.AsQueryable(), lambda); + Assert.Equal(res6, list[3]); + + var res7 = DynamicQueryableExtensions.LastOrDefault(list.AsQueryable(), lambda); + Assert.Equal(res7, list[3]); + + var res8 = DynamicQueryableExtensions.Single(list.AsQueryable().Take(2), lambda); + Assert.Equal(res8, list[1]); + + var res9 = DynamicQueryableExtensions.SingleOrDefault(list.AsQueryable().Take(2), lambda); + Assert.Equal(res9, list[1]); } } } \ No newline at end of file From 39e50ee7694bf88c3537a753573b8f4c760255ff Mon Sep 17 00:00:00 2001 From: jogibear9988 Date: Tue, 16 May 2017 09:36:29 +0200 Subject: [PATCH 5/7] Unit Tests for Last and Single --- .../EntitiesTests.Count.cs | 66 ++++++++++++++++++- .../EntitiesTests.LastAndSingle.cs | 28 ++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs diff --git a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs index 18a07fa9..091602b8 100644 --- a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs +++ b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs @@ -6,7 +6,7 @@ namespace System.Linq.Dynamic.Core.Tests public partial class EntitiesTests { [Fact] - public void Entities_Count_Predicate() + public void Entities_Last_Predicate() { const string search = "a"; @@ -18,8 +18,68 @@ public void Entities_Count_Predicate() _context.SaveChanges(); //Act - int expected = _context.Blogs.Count(b => b.Name.Contains(search)); - int result = _context.Blogs.Count("Name.Contains(@0)", search); + var expected = _context.Blogs.Last(b => b.Name.Contains(search)); + var result = _context.Blogs.Last("Name.Contains(@0)", search); + + //Assert + Assert.Equal(expected, result); + } + + [Fact] + public void Entities_LastOrDefault_Predicate() + { + const string search = "a"; + + //Arrange + var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; + var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; + _context.Blogs.Add(blog1); + _context.Blogs.Add(blog2); + _context.SaveChanges(); + + //Act + var expected = _context.Blogs.LastOrDefault(b => b.Name.Contains(search)); + var result = _context.Blogs.LastOrDefault("Name.Contains(@0)", search); + + //Assert + Assert.Equal(expected, result); + } + + [Fact] + public void Entities_Single_Predicate() + { + const string search = "a"; + + //Arrange + var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; + var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; + _context.Blogs.Add(blog1); + _context.Blogs.Add(blog2); + _context.SaveChanges(); + + //Act + var expected = _context.Blogs.Single(b => b.Name.Contains(search)); + var result = _context.Blogs.Single("Name.Contains(@0)", search); + + //Assert + Assert.Equal(expected, result); + } + + [Fact] + public void Entities_SingleOrDefault_Predicate() + { + const string search = "a"; + + //Arrange + var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; + var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; + _context.Blogs.Add(blog1); + _context.Blogs.Add(blog2); + _context.SaveChanges(); + + //Act + var expected = _context.Blogs.SingleOrDefault(b => b.Name.Contains(search)); + var result = _context.Blogs.SingleOrDefault("Name.Contains(@0)", search); //Assert Assert.Equal(expected, result); diff --git a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs new file mode 100644 index 00000000..18a07fa9 --- /dev/null +++ b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs @@ -0,0 +1,28 @@ +using System.Linq.Dynamic.Core.Tests.Helpers.Entities; +using Xunit; + +namespace System.Linq.Dynamic.Core.Tests +{ + public partial class EntitiesTests + { + [Fact] + public void Entities_Count_Predicate() + { + const string search = "a"; + + //Arrange + var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; + var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; + _context.Blogs.Add(blog1); + _context.Blogs.Add(blog2); + _context.SaveChanges(); + + //Act + int expected = _context.Blogs.Count(b => b.Name.Contains(search)); + int result = _context.Blogs.Count("Name.Contains(@0)", search); + + //Assert + Assert.Equal(expected, result); + } + } +} \ No newline at end of file From 51d3daf46e246b3281ce51f50d1d85c8c30e4d37 Mon Sep 17 00:00:00 2001 From: jogibear9988 Date: Tue, 16 May 2017 10:59:07 +0200 Subject: [PATCH 6/7] Fix wrong editited files --- .../EntitiesTests.Count.cs | 66 +------------------ .../EntitiesTests.LastAndSingle.cs | 66 ++++++++++++++++++- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs index 091602b8..18a07fa9 100644 --- a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs +++ b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.Count.cs @@ -6,7 +6,7 @@ namespace System.Linq.Dynamic.Core.Tests public partial class EntitiesTests { [Fact] - public void Entities_Last_Predicate() + public void Entities_Count_Predicate() { const string search = "a"; @@ -18,68 +18,8 @@ public void Entities_Last_Predicate() _context.SaveChanges(); //Act - var expected = _context.Blogs.Last(b => b.Name.Contains(search)); - var result = _context.Blogs.Last("Name.Contains(@0)", search); - - //Assert - Assert.Equal(expected, result); - } - - [Fact] - public void Entities_LastOrDefault_Predicate() - { - const string search = "a"; - - //Arrange - var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; - var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; - _context.Blogs.Add(blog1); - _context.Blogs.Add(blog2); - _context.SaveChanges(); - - //Act - var expected = _context.Blogs.LastOrDefault(b => b.Name.Contains(search)); - var result = _context.Blogs.LastOrDefault("Name.Contains(@0)", search); - - //Assert - Assert.Equal(expected, result); - } - - [Fact] - public void Entities_Single_Predicate() - { - const string search = "a"; - - //Arrange - var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; - var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; - _context.Blogs.Add(blog1); - _context.Blogs.Add(blog2); - _context.SaveChanges(); - - //Act - var expected = _context.Blogs.Single(b => b.Name.Contains(search)); - var result = _context.Blogs.Single("Name.Contains(@0)", search); - - //Assert - Assert.Equal(expected, result); - } - - [Fact] - public void Entities_SingleOrDefault_Predicate() - { - const string search = "a"; - - //Arrange - var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; - var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; - _context.Blogs.Add(blog1); - _context.Blogs.Add(blog2); - _context.SaveChanges(); - - //Act - var expected = _context.Blogs.SingleOrDefault(b => b.Name.Contains(search)); - var result = _context.Blogs.SingleOrDefault("Name.Contains(@0)", search); + int expected = _context.Blogs.Count(b => b.Name.Contains(search)); + int result = _context.Blogs.Count("Name.Contains(@0)", search); //Assert Assert.Equal(expected, result); diff --git a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs index 18a07fa9..091602b8 100644 --- a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs +++ b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs @@ -6,7 +6,7 @@ namespace System.Linq.Dynamic.Core.Tests public partial class EntitiesTests { [Fact] - public void Entities_Count_Predicate() + public void Entities_Last_Predicate() { const string search = "a"; @@ -18,8 +18,68 @@ public void Entities_Count_Predicate() _context.SaveChanges(); //Act - int expected = _context.Blogs.Count(b => b.Name.Contains(search)); - int result = _context.Blogs.Count("Name.Contains(@0)", search); + var expected = _context.Blogs.Last(b => b.Name.Contains(search)); + var result = _context.Blogs.Last("Name.Contains(@0)", search); + + //Assert + Assert.Equal(expected, result); + } + + [Fact] + public void Entities_LastOrDefault_Predicate() + { + const string search = "a"; + + //Arrange + var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; + var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; + _context.Blogs.Add(blog1); + _context.Blogs.Add(blog2); + _context.SaveChanges(); + + //Act + var expected = _context.Blogs.LastOrDefault(b => b.Name.Contains(search)); + var result = _context.Blogs.LastOrDefault("Name.Contains(@0)", search); + + //Assert + Assert.Equal(expected, result); + } + + [Fact] + public void Entities_Single_Predicate() + { + const string search = "a"; + + //Arrange + var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; + var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; + _context.Blogs.Add(blog1); + _context.Blogs.Add(blog2); + _context.SaveChanges(); + + //Act + var expected = _context.Blogs.Single(b => b.Name.Contains(search)); + var result = _context.Blogs.Single("Name.Contains(@0)", search); + + //Assert + Assert.Equal(expected, result); + } + + [Fact] + public void Entities_SingleOrDefault_Predicate() + { + const string search = "a"; + + //Arrange + var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; + var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; + _context.Blogs.Add(blog1); + _context.Blogs.Add(blog2); + _context.SaveChanges(); + + //Act + var expected = _context.Blogs.SingleOrDefault(b => b.Name.Contains(search)); + var result = _context.Blogs.SingleOrDefault("Name.Contains(@0)", search); //Assert Assert.Equal(expected, result); From b1c54d517226e07d7415cf99dc082a7e07bbcf6a Mon Sep 17 00:00:00 2001 From: jogibear9988 Date: Tue, 16 May 2017 11:10:55 +0200 Subject: [PATCH 7/7] Fix Unitests with Last & Single --- .../EntitiesTests.LastAndSingle.cs | 88 ------------------- .../QueryableTests.Last.cs | 30 +++++++ .../QueryableTests.Single.cs | 30 +++++++ 3 files changed, 60 insertions(+), 88 deletions(-) delete mode 100644 test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs diff --git a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs deleted file mode 100644 index 091602b8..00000000 --- a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.LastAndSingle.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Linq.Dynamic.Core.Tests.Helpers.Entities; -using Xunit; - -namespace System.Linq.Dynamic.Core.Tests -{ - public partial class EntitiesTests - { - [Fact] - public void Entities_Last_Predicate() - { - const string search = "a"; - - //Arrange - var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; - var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; - _context.Blogs.Add(blog1); - _context.Blogs.Add(blog2); - _context.SaveChanges(); - - //Act - var expected = _context.Blogs.Last(b => b.Name.Contains(search)); - var result = _context.Blogs.Last("Name.Contains(@0)", search); - - //Assert - Assert.Equal(expected, result); - } - - [Fact] - public void Entities_LastOrDefault_Predicate() - { - const string search = "a"; - - //Arrange - var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; - var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; - _context.Blogs.Add(blog1); - _context.Blogs.Add(blog2); - _context.SaveChanges(); - - //Act - var expected = _context.Blogs.LastOrDefault(b => b.Name.Contains(search)); - var result = _context.Blogs.LastOrDefault("Name.Contains(@0)", search); - - //Assert - Assert.Equal(expected, result); - } - - [Fact] - public void Entities_Single_Predicate() - { - const string search = "a"; - - //Arrange - var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; - var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; - _context.Blogs.Add(blog1); - _context.Blogs.Add(blog2); - _context.SaveChanges(); - - //Act - var expected = _context.Blogs.Single(b => b.Name.Contains(search)); - var result = _context.Blogs.Single("Name.Contains(@0)", search); - - //Assert - Assert.Equal(expected, result); - } - - [Fact] - public void Entities_SingleOrDefault_Predicate() - { - const string search = "a"; - - //Arrange - var blog1 = new Blog { Name = "blog a", BlogId = 1000 }; - var blog2 = new Blog { Name = "blog b", BlogId = 3000 }; - _context.Blogs.Add(blog1); - _context.Blogs.Add(blog2); - _context.SaveChanges(); - - //Act - var expected = _context.Blogs.SingleOrDefault(b => b.Name.Contains(search)); - var result = _context.Blogs.SingleOrDefault("Name.Contains(@0)", search); - - //Assert - Assert.Equal(expected, result); - } - } -} \ No newline at end of file diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Last.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Last.cs index af0154f6..7546a80e 100644 --- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Last.cs +++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Last.cs @@ -24,6 +24,21 @@ public void Last() #endif } + [Fact] + public void Last_Predicate() + { + //Arrange + var testList = User.GenerateSampleModels(100); + var queryable = testList.AsQueryable(); + + //Act + var expected = queryable.Last(u => u.Income > 1000); + var result = queryable.Last("Income > 1000"); + + //Assert + Assert.Equal(expected as object, result); + } + [Fact] public void LastOrDefault() { @@ -45,6 +60,21 @@ public void LastOrDefault() Assert.Null(defaultResult); } + [Fact] + public void LastOrDefault_Predicate() + { + //Arrange + var testList = User.GenerateSampleModels(100); + var queryable = testList.AsQueryable(); + + //Act + var expected = queryable.LastOrDefault(u => u.Income > 1000); + var result = queryable.LastOrDefault("Income > 1000"); + + //Assert + Assert.Equal(expected as object, result); + } + [Fact] public void Last_Dynamic() { diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Single.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Single.cs index 8cad5e71..431e80eb 100644 --- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Single.cs +++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Single.cs @@ -23,6 +23,21 @@ public void Single() #endif } + [Fact] + public void Single_Predicate() + { + //Arrange + var testList = User.GenerateSampleModels(100); + var testListQry = testList.AsQueryable(); + + //Act + var expected = testListQry.Single(u => u.UserName == "User4"); + var result = testListQry.Single("UserName == \"User4\""); + + //Assert + Assert.Equal(expected as object, result); + } + [Fact] public void SingleOrDefault() { @@ -43,6 +58,21 @@ public void SingleOrDefault() Assert.Null(defaultResult); } + [Fact] + public void SingleOrDefault_Predicate() + { + //Arrange + var testList = User.GenerateSampleModels(100); + var testListQry = testList.AsQueryable(); + + //Act + var expected = testListQry.SingleOrDefault(u => u.UserName == "User4"); + var result = testListQry.SingleOrDefault("UserName == \"User4\""); + + //Assert + Assert.Equal(expected as object, result); + } + [Fact] public void Single_Dynamic() {