From 06f41ab8076014a0e34f75248085df24fd924acf Mon Sep 17 00:00:00 2001 From: Fati Iseni Date: Fri, 14 Mar 2025 15:17:51 +0100 Subject: [PATCH 1/3] Add inheritance in the builders. --- .../Builders/Builder_Cache.cs | 29 +++----- .../Builders/Builder_Flags.cs | 72 ++++++++----------- .../Builders/Builder_Include.cs | 41 +++-------- .../Builders/Builder_Order.cs | 38 ++-------- .../Builders/Builder_Paging.cs | 14 +--- .../Builders/Builder_Search.cs | 7 +- .../Builders/Builder_TagWith.cs | 6 +- .../Builders/Builder_Where.cs | 7 +- .../IncludableSpecificationBuilder.cs | 6 +- .../Builders/SpecificationBuilder.cs | 22 +++--- 10 files changed, 75 insertions(+), 167 deletions(-) diff --git a/src/Ardalis.Specification/Builders/Builder_Cache.cs b/src/Ardalis.Specification/Builders/Builder_Cache.cs index 0ac4c77e..6be1d9d8 100644 --- a/src/Ardalis.Specification/Builders/Builder_Cache.cs +++ b/src/Ardalis.Specification/Builders/Builder_Cache.cs @@ -16,7 +16,10 @@ public static ICacheSpecificationBuilder EnableCache( this ISpecificationBuilder builder, string specificationName, params object[] args) where T : class - => EnableCache(builder, specificationName, true, args); + { + ((ISpecificationBuilder)builder).EnableCache(specificationName, true, args); + return (SpecificationBuilder)builder; + } /// /// Set's the cache key for the specification. @@ -35,17 +38,7 @@ public static ICacheSpecificationBuilder EnableCache( bool condition, params object[] args) where T : class { - if (condition) - { - if (string.IsNullOrEmpty(specificationName)) - { - throw new ArgumentException($"Required input {specificationName} was null or empty.", specificationName); - } - - builder.Specification.CacheKey = $"{specificationName}-{string.Join("-", args)}"; - } - - Specification.IsChainDiscarded = !condition; + ((ISpecificationBuilder)builder).EnableCache(specificationName, condition, args); return (SpecificationBuilder)builder; } @@ -106,7 +99,10 @@ public static ICacheSpecificationBuilder EnableCache( public static ICacheSpecificationBuilder WithCacheKey( this ISpecificationBuilder builder, string cacheKey) where T : class - => WithCacheKey(builder, cacheKey, true); + { + ((ISpecificationBuilder)builder).WithCacheKey(cacheKey, true); + return (SpecificationBuilder)builder; + } /// /// Sets the cache key for the specification. @@ -123,12 +119,7 @@ public static ICacheSpecificationBuilder WithCacheKey( string cacheKey, bool condition) where T : class { - if (condition) - { - builder.Specification.CacheKey = cacheKey; - } - - Specification.IsChainDiscarded = !condition; + ((ISpecificationBuilder)builder).WithCacheKey(cacheKey, condition); return (SpecificationBuilder)builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Flags.cs b/src/Ardalis.Specification/Builders/Builder_Flags.cs index 6b3bb738..e54bae5f 100644 --- a/src/Ardalis.Specification/Builders/Builder_Flags.cs +++ b/src/Ardalis.Specification/Builders/Builder_Flags.cs @@ -11,7 +11,10 @@ public static partial class SpecificationBuilderExtensions /// The updated specification builder. public static ISpecificationBuilder IgnoreQueryFilters( this ISpecificationBuilder builder) where T : class - => IgnoreQueryFilters(builder, true); + { + ((ISpecificationBuilder)builder).IgnoreQueryFilters(true); + return builder; + } /// /// Configures the specification to ignore query filters if the condition is true. @@ -25,11 +28,7 @@ public static ISpecificationBuilder IgnoreQueryFilters( this ISpecificationBuilder builder, bool condition) where T : class { - if (condition) - { - builder.Specification.IgnoreQueryFilters = true; - } - + ((ISpecificationBuilder)builder).IgnoreQueryFilters(condition); return builder; } @@ -71,7 +70,10 @@ public static ISpecificationBuilder IgnoreQueryFilters( /// The updated specification builder. public static ISpecificationBuilder IgnoreAutoIncludes( this ISpecificationBuilder builder) where T : class - => IgnoreAutoIncludes(builder, true); + { + ((ISpecificationBuilder)builder).IgnoreAutoIncludes(true); + return builder; + } /// /// Configures the specification to ignore auto includes if the condition is true. @@ -85,11 +87,7 @@ public static ISpecificationBuilder IgnoreAutoIncludes( this ISpecificationBuilder builder, bool condition) where T : class { - if (condition) - { - builder.Specification.IgnoreAutoIncludes = true; - } - + ((ISpecificationBuilder)builder).IgnoreAutoIncludes(condition); return builder; } @@ -131,7 +129,10 @@ public static ISpecificationBuilder IgnoreAutoIncludes( /// The updated specification builder. public static ISpecificationBuilder AsSplitQuery( this ISpecificationBuilder builder) where T : class - => AsSplitQuery(builder, true); + { + ((ISpecificationBuilder)builder).AsSplitQuery(true); + return builder; + } /// /// Configures the specification to use split queries if the condition is true. @@ -145,11 +146,7 @@ public static ISpecificationBuilder AsSplitQuery( this ISpecificationBuilder builder, bool condition) where T : class { - if (condition) - { - builder.Specification.AsSplitQuery = true; - } - + ((ISpecificationBuilder)builder).AsSplitQuery(condition); return builder; } @@ -192,7 +189,10 @@ public static ISpecificationBuilder AsSplitQuery( /// The updated specification builder. public static ISpecificationBuilder AsNoTracking( this ISpecificationBuilder builder) where T : class - => AsNoTracking(builder, true); + { + ((ISpecificationBuilder)builder).AsNoTracking(true); + return builder; + } /// /// Configures the specification to apply NoTracking behavior if the condition is true. @@ -207,13 +207,7 @@ public static ISpecificationBuilder AsNoTracking( this ISpecificationBuilder builder, bool condition) where T : class { - if (condition) - { - builder.Specification.AsTracking = false; - builder.Specification.AsNoTrackingWithIdentityResolution = false; - builder.Specification.AsNoTracking = true; - } - + ((ISpecificationBuilder)builder).AsNoTracking(condition); return builder; } @@ -260,7 +254,10 @@ public static ISpecificationBuilder AsNoTracking( /// The updated specification builder. public static ISpecificationBuilder AsNoTrackingWithIdentityResolution( this ISpecificationBuilder builder) where T : class - => AsNoTrackingWithIdentityResolution(builder, true); + { + ((ISpecificationBuilder)builder).AsNoTrackingWithIdentityResolution(true); + return builder; + } /// /// Configures the specification to apply AsNoTrackingWithIdentityResolution behavior if the condition is true. @@ -275,13 +272,7 @@ public static ISpecificationBuilder AsNoTrackingWithIdentityResoluti this ISpecificationBuilder builder, bool condition) where T : class { - if (condition) - { - builder.Specification.AsTracking = false; - builder.Specification.AsNoTracking = false; - builder.Specification.AsNoTrackingWithIdentityResolution = true; - } - + ((ISpecificationBuilder)builder).AsNoTrackingWithIdentityResolution(condition); return builder; } @@ -328,7 +319,10 @@ public static ISpecificationBuilder AsNoTrackingWithIdentityResolution( /// The updated specification builder. public static ISpecificationBuilder AsTracking( this ISpecificationBuilder builder) where T : class - => AsTracking(builder, true); + { + ((ISpecificationBuilder)builder).AsTracking(true); + return builder; + } /// /// Configures the specification to apply AsTracking behavior if the condition is true. @@ -343,13 +337,7 @@ public static ISpecificationBuilder AsTracking( this ISpecificationBuilder builder, bool condition) where T : class { - if (condition) - { - builder.Specification.AsNoTracking = false; - builder.Specification.AsNoTrackingWithIdentityResolution = false; - builder.Specification.AsTracking = true; - } - + ((ISpecificationBuilder)builder).AsTracking(condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Include.cs b/src/Ardalis.Specification/Builders/Builder_Include.cs index f31087b9..1471e004 100644 --- a/src/Ardalis.Specification/Builders/Builder_Include.cs +++ b/src/Ardalis.Specification/Builders/Builder_Include.cs @@ -13,7 +13,10 @@ public static partial class SpecificationBuilderExtensions public static ISpecificationBuilder Include( this ISpecificationBuilder builder, string includeString) where T : class - => Include(builder, includeString, true); + { + ((ISpecificationBuilder)builder).Include(includeString, true); + return builder; + } /// /// Adds an Include clause to the specification if the condition is true. @@ -29,11 +32,7 @@ public static ISpecificationBuilder Include( string includeString, bool condition) where T : class { - if (condition) - { - builder.Specification.Add(includeString); - } - + ((ISpecificationBuilder)builder).Include(includeString, condition); return builder; } @@ -99,13 +98,7 @@ public static IIncludableSpecificationBuilder Include> navigationSelector, bool condition) where T : class { - if (condition) - { - var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.Include); - builder.Specification.Add(expr); - } - - Specification.IsChainDiscarded = !condition; + ((ISpecificationBuilder)builder).Include(navigationSelector, condition); var includeBuilder = new IncludableSpecificationBuilder(builder.Specification); return includeBuilder; } @@ -181,16 +174,7 @@ public static IIncludableSpecificationBuilder ThenI bool condition) where TEntity : class { - if (condition && !Specification.IsChainDiscarded) - { - var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude); - builder.Specification.Add(expr); - } - else - { - Specification.IsChainDiscarded = true; - } - + ((IIncludableSpecificationBuilder)builder).ThenInclude(navigationSelector, condition); var includeBuilder = new IncludableSpecificationBuilder(builder.Specification); return includeBuilder; } @@ -273,16 +257,7 @@ public static IIncludableSpecificationBuilder ThenI bool condition) where TEntity : class { - if (condition && !Specification.IsChainDiscarded) - { - var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude); - builder.Specification.Add(expr); - } - else - { - Specification.IsChainDiscarded = true; - } - + ((IIncludableSpecificationBuilder>)builder).ThenInclude(navigationSelector, condition); var includeBuilder = new IncludableSpecificationBuilder(builder.Specification); return includeBuilder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Order.cs b/src/Ardalis.Specification/Builders/Builder_Order.cs index 20714370..ff899540 100644 --- a/src/Ardalis.Specification/Builders/Builder_Order.cs +++ b/src/Ardalis.Specification/Builders/Builder_Order.cs @@ -29,13 +29,7 @@ public static IOrderedSpecificationBuilder OrderBy( Expression> keySelector, bool condition) { - if (condition) - { - var expr = new OrderExpressionInfo(keySelector, OrderTypeEnum.OrderBy); - builder.Specification.Add(expr); - } - - Specification.IsChainDiscarded = !condition; + ((ISpecificationBuilder)builder).OrderBy(keySelector, condition); return (SpecificationBuilder)builder; } @@ -101,13 +95,7 @@ public static IOrderedSpecificationBuilder OrderByDescending> keySelector, bool condition) { - if (condition) - { - var expr = new OrderExpressionInfo(keySelector, OrderTypeEnum.OrderByDescending); - builder.Specification.Add(expr); - } - - Specification.IsChainDiscarded = !condition; + ((ISpecificationBuilder)builder).OrderByDescending(keySelector, condition); return (SpecificationBuilder)builder; } @@ -173,16 +161,7 @@ public static IOrderedSpecificationBuilder ThenBy( Expression> keySelector, bool condition) { - if (condition && !Specification.IsChainDiscarded) - { - var expr = new OrderExpressionInfo(keySelector, OrderTypeEnum.ThenBy); - builder.Specification.Add(expr); - } - else - { - Specification.IsChainDiscarded = true; - } - + ((IOrderedSpecificationBuilder)builder).ThenBy(keySelector, condition); return builder; } @@ -251,16 +230,7 @@ public static IOrderedSpecificationBuilder ThenByDescending> keySelector, bool condition) { - if (condition && !Specification.IsChainDiscarded) - { - var expr = new OrderExpressionInfo(keySelector, OrderTypeEnum.ThenByDescending); - builder.Specification.Add(expr); - } - else - { - Specification.IsChainDiscarded = true; - } - + ((IOrderedSpecificationBuilder)builder).ThenByDescending(keySelector, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Paging.cs b/src/Ardalis.Specification/Builders/Builder_Paging.cs index 8a3b431a..83fadc73 100644 --- a/src/Ardalis.Specification/Builders/Builder_Paging.cs +++ b/src/Ardalis.Specification/Builders/Builder_Paging.cs @@ -31,12 +31,7 @@ public static ISpecificationBuilder Take( int take, bool condition) { - if (condition) - { - if (builder.Specification.Take != -1) throw new DuplicateTakeException(); - builder.Specification.Take = take; - } - + ((ISpecificationBuilder)builder).Take(take, condition); return builder; } @@ -105,12 +100,7 @@ public static ISpecificationBuilder Skip( int skip, bool condition) { - if (condition) - { - if (builder.Specification.Skip != -1) throw new DuplicateSkipException(); - builder.Specification.Skip = skip; - } - + ((ISpecificationBuilder)builder).Skip(skip, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Search.cs b/src/Ardalis.Specification/Builders/Builder_Search.cs index a4f12407..8aae1e85 100644 --- a/src/Ardalis.Specification/Builders/Builder_Search.cs +++ b/src/Ardalis.Specification/Builders/Builder_Search.cs @@ -39,12 +39,7 @@ public static ISpecificationBuilder Search( bool condition, int group = 1) where T : class { - if (condition) - { - var expr = new SearchExpressionInfo(keySelector, pattern, group); - builder.Specification.Add(expr); - } - + ((ISpecificationBuilder)builder).Search(keySelector, pattern, condition, group); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_TagWith.cs b/src/Ardalis.Specification/Builders/Builder_TagWith.cs index 421fad6a..29a6a3e6 100644 --- a/src/Ardalis.Specification/Builders/Builder_TagWith.cs +++ b/src/Ardalis.Specification/Builders/Builder_TagWith.cs @@ -29,11 +29,7 @@ public static ISpecificationBuilder TagWith( string tag, bool condition) { - if (condition) - { - builder.Specification.QueryTag = tag; - } - + ((ISpecificationBuilder)builder).TagWith(tag, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Where.cs b/src/Ardalis.Specification/Builders/Builder_Where.cs index 49800b86..8a2a382f 100644 --- a/src/Ardalis.Specification/Builders/Builder_Where.cs +++ b/src/Ardalis.Specification/Builders/Builder_Where.cs @@ -29,12 +29,7 @@ public static ISpecificationBuilder Where( Expression> predicate, bool condition) { - if (condition) - { - var expr = new WhereExpressionInfo(predicate); - builder.Specification.Add(expr); - } - + ((ISpecificationBuilder)builder).Where(predicate, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/IncludableSpecificationBuilder.cs b/src/Ardalis.Specification/Builders/IncludableSpecificationBuilder.cs index 4c84b981..70877ed7 100644 --- a/src/Ardalis.Specification/Builders/IncludableSpecificationBuilder.cs +++ b/src/Ardalis.Specification/Builders/IncludableSpecificationBuilder.cs @@ -1,10 +1,12 @@ namespace Ardalis.Specification; -public interface IIncludableSpecificationBuilder : ISpecificationBuilder where T : class +public interface IIncludableSpecificationBuilder + : ISpecificationBuilder, IIncludableSpecificationBuilder where T : class { } -public interface IIncludableSpecificationBuilder : ISpecificationBuilder where T : class +public interface IIncludableSpecificationBuilder + : ISpecificationBuilder where T : class { } diff --git a/src/Ardalis.Specification/Builders/SpecificationBuilder.cs b/src/Ardalis.Specification/Builders/SpecificationBuilder.cs index aa2f00bf..718cc3c4 100644 --- a/src/Ardalis.Specification/Builders/SpecificationBuilder.cs +++ b/src/Ardalis.Specification/Builders/SpecificationBuilder.cs @@ -1,24 +1,29 @@ namespace Ardalis.Specification; -public interface ICacheSpecificationBuilder : ISpecificationBuilder +public interface ICacheSpecificationBuilder + : ISpecificationBuilder, ICacheSpecificationBuilder { } -public interface ICacheSpecificationBuilder : ISpecificationBuilder +public interface ICacheSpecificationBuilder + : ISpecificationBuilder { } -public interface IOrderedSpecificationBuilder : ISpecificationBuilder +public interface IOrderedSpecificationBuilder + : ISpecificationBuilder, IOrderedSpecificationBuilder { } -public interface IOrderedSpecificationBuilder : ISpecificationBuilder +public interface IOrderedSpecificationBuilder + : ISpecificationBuilder { } public interface ISpecificationBuilder + : ISpecificationBuilder { - Specification Specification { get; } + new Specification Specification { get; } } public interface ISpecificationBuilder @@ -26,12 +31,13 @@ public interface ISpecificationBuilder Specification Specification { get; } } -internal class SpecificationBuilder - : ICacheSpecificationBuilder, IOrderedSpecificationBuilder, ISpecificationBuilder +internal class SpecificationBuilder : SpecificationBuilder, + ICacheSpecificationBuilder, IOrderedSpecificationBuilder, ISpecificationBuilder { - public Specification Specification { get; } + public new Specification Specification { get; } public SpecificationBuilder(Specification specification) + :base(specification) { Specification = specification; } From c234c91613e455fa1cfc0f90ac5767188293e4f4 Mon Sep 17 00:00:00 2001 From: Fati Iseni Date: Fri, 14 Mar 2025 17:16:56 +0200 Subject: [PATCH 2/3] Cleanup. --- .../Builders/Builder_Cache.cs | 8 ++-- .../Builders/Builder_Flags.cs | 24 +++++------ .../Builders/Builder_Include.cs | 41 +++++++++++++++---- .../Builders/Builder_Order.cs | 28 +++++++++---- .../Builders/Builder_Paging.cs | 14 +++++-- .../Builders/Builder_Search.cs | 7 +++- .../Builders/Builder_TagWith.cs | 7 +++- .../Builders/Builder_Where.cs | 7 +++- 8 files changed, 94 insertions(+), 42 deletions(-) diff --git a/src/Ardalis.Specification/Builders/Builder_Cache.cs b/src/Ardalis.Specification/Builders/Builder_Cache.cs index 6be1d9d8..7c7f547a 100644 --- a/src/Ardalis.Specification/Builders/Builder_Cache.cs +++ b/src/Ardalis.Specification/Builders/Builder_Cache.cs @@ -17,7 +17,7 @@ public static ICacheSpecificationBuilder EnableCache( string specificationName, params object[] args) where T : class { - ((ISpecificationBuilder)builder).EnableCache(specificationName, true, args); + EnableCache((ISpecificationBuilder)builder, specificationName, true, args); return (SpecificationBuilder)builder; } @@ -38,7 +38,7 @@ public static ICacheSpecificationBuilder EnableCache( bool condition, params object[] args) where T : class { - ((ISpecificationBuilder)builder).EnableCache(specificationName, condition, args); + EnableCache((ISpecificationBuilder)builder, specificationName, condition, args); return (SpecificationBuilder)builder; } @@ -100,7 +100,7 @@ public static ICacheSpecificationBuilder WithCacheKey( this ISpecificationBuilder builder, string cacheKey) where T : class { - ((ISpecificationBuilder)builder).WithCacheKey(cacheKey, true); + WithCacheKey((ISpecificationBuilder)builder, cacheKey, true); return (SpecificationBuilder)builder; } @@ -119,7 +119,7 @@ public static ICacheSpecificationBuilder WithCacheKey( string cacheKey, bool condition) where T : class { - ((ISpecificationBuilder)builder).WithCacheKey(cacheKey, condition); + WithCacheKey((ISpecificationBuilder)builder, cacheKey, condition); return (SpecificationBuilder)builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Flags.cs b/src/Ardalis.Specification/Builders/Builder_Flags.cs index e54bae5f..769ada32 100644 --- a/src/Ardalis.Specification/Builders/Builder_Flags.cs +++ b/src/Ardalis.Specification/Builders/Builder_Flags.cs @@ -12,7 +12,7 @@ public static partial class SpecificationBuilderExtensions public static ISpecificationBuilder IgnoreQueryFilters( this ISpecificationBuilder builder) where T : class { - ((ISpecificationBuilder)builder).IgnoreQueryFilters(true); + IgnoreQueryFilters((ISpecificationBuilder)builder, true); return builder; } @@ -28,7 +28,7 @@ public static ISpecificationBuilder IgnoreQueryFilters( this ISpecificationBuilder builder, bool condition) where T : class { - ((ISpecificationBuilder)builder).IgnoreQueryFilters(condition); + IgnoreQueryFilters((ISpecificationBuilder)builder, condition); return builder; } @@ -71,7 +71,7 @@ public static ISpecificationBuilder IgnoreQueryFilters( public static ISpecificationBuilder IgnoreAutoIncludes( this ISpecificationBuilder builder) where T : class { - ((ISpecificationBuilder)builder).IgnoreAutoIncludes(true); + IgnoreAutoIncludes((ISpecificationBuilder)builder, true); return builder; } @@ -87,7 +87,7 @@ public static ISpecificationBuilder IgnoreAutoIncludes( this ISpecificationBuilder builder, bool condition) where T : class { - ((ISpecificationBuilder)builder).IgnoreAutoIncludes(condition); + IgnoreAutoIncludes((ISpecificationBuilder)builder, condition); return builder; } @@ -130,7 +130,7 @@ public static ISpecificationBuilder IgnoreAutoIncludes( public static ISpecificationBuilder AsSplitQuery( this ISpecificationBuilder builder) where T : class { - ((ISpecificationBuilder)builder).AsSplitQuery(true); + AsSplitQuery((ISpecificationBuilder)builder, true); return builder; } @@ -146,7 +146,7 @@ public static ISpecificationBuilder AsSplitQuery( this ISpecificationBuilder builder, bool condition) where T : class { - ((ISpecificationBuilder)builder).AsSplitQuery(condition); + AsSplitQuery((ISpecificationBuilder)builder, condition); return builder; } @@ -190,7 +190,7 @@ public static ISpecificationBuilder AsSplitQuery( public static ISpecificationBuilder AsNoTracking( this ISpecificationBuilder builder) where T : class { - ((ISpecificationBuilder)builder).AsNoTracking(true); + AsNoTracking((ISpecificationBuilder)builder, true); return builder; } @@ -207,7 +207,7 @@ public static ISpecificationBuilder AsNoTracking( this ISpecificationBuilder builder, bool condition) where T : class { - ((ISpecificationBuilder)builder).AsNoTracking(condition); + AsNoTracking((ISpecificationBuilder)builder, condition); return builder; } @@ -255,7 +255,7 @@ public static ISpecificationBuilder AsNoTracking( public static ISpecificationBuilder AsNoTrackingWithIdentityResolution( this ISpecificationBuilder builder) where T : class { - ((ISpecificationBuilder)builder).AsNoTrackingWithIdentityResolution(true); + AsNoTrackingWithIdentityResolution((ISpecificationBuilder)builder, true); return builder; } @@ -272,7 +272,7 @@ public static ISpecificationBuilder AsNoTrackingWithIdentityResoluti this ISpecificationBuilder builder, bool condition) where T : class { - ((ISpecificationBuilder)builder).AsNoTrackingWithIdentityResolution(condition); + AsNoTrackingWithIdentityResolution((ISpecificationBuilder)builder, condition); return builder; } @@ -320,7 +320,7 @@ public static ISpecificationBuilder AsNoTrackingWithIdentityResolution( public static ISpecificationBuilder AsTracking( this ISpecificationBuilder builder) where T : class { - ((ISpecificationBuilder)builder).AsTracking(true); + AsTracking((ISpecificationBuilder)builder, true); return builder; } @@ -337,7 +337,7 @@ public static ISpecificationBuilder AsTracking( this ISpecificationBuilder builder, bool condition) where T : class { - ((ISpecificationBuilder)builder).AsTracking(condition); + AsTracking((ISpecificationBuilder)builder, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Include.cs b/src/Ardalis.Specification/Builders/Builder_Include.cs index 1471e004..ee7ec96e 100644 --- a/src/Ardalis.Specification/Builders/Builder_Include.cs +++ b/src/Ardalis.Specification/Builders/Builder_Include.cs @@ -13,10 +13,7 @@ public static partial class SpecificationBuilderExtensions public static ISpecificationBuilder Include( this ISpecificationBuilder builder, string includeString) where T : class - { - ((ISpecificationBuilder)builder).Include(includeString, true); - return builder; - } + => Include(builder, includeString, true); /// /// Adds an Include clause to the specification if the condition is true. @@ -32,7 +29,11 @@ public static ISpecificationBuilder Include( string includeString, bool condition) where T : class { - ((ISpecificationBuilder)builder).Include(includeString, condition); + if (condition) + { + builder.Specification.Add(includeString); + } + return builder; } @@ -98,7 +99,13 @@ public static IIncludableSpecificationBuilder Include> navigationSelector, bool condition) where T : class { - ((ISpecificationBuilder)builder).Include(navigationSelector, condition); + if (condition) + { + var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.Include); + builder.Specification.Add(expr); + } + + Specification.IsChainDiscarded = !condition; var includeBuilder = new IncludableSpecificationBuilder(builder.Specification); return includeBuilder; } @@ -174,7 +181,16 @@ public static IIncludableSpecificationBuilder ThenI bool condition) where TEntity : class { - ((IIncludableSpecificationBuilder)builder).ThenInclude(navigationSelector, condition); + if (condition && !Specification.IsChainDiscarded) + { + var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude); + builder.Specification.Add(expr); + } + else + { + Specification.IsChainDiscarded = true; + } + var includeBuilder = new IncludableSpecificationBuilder(builder.Specification); return includeBuilder; } @@ -257,7 +273,16 @@ public static IIncludableSpecificationBuilder ThenI bool condition) where TEntity : class { - ((IIncludableSpecificationBuilder>)builder).ThenInclude(navigationSelector, condition); + if (condition && !Specification.IsChainDiscarded) + { + var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude); + builder.Specification.Add(expr); + } + else + { + Specification.IsChainDiscarded = true; + } + var includeBuilder = new IncludableSpecificationBuilder(builder.Specification); return includeBuilder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Order.cs b/src/Ardalis.Specification/Builders/Builder_Order.cs index ff899540..d10f20f6 100644 --- a/src/Ardalis.Specification/Builders/Builder_Order.cs +++ b/src/Ardalis.Specification/Builders/Builder_Order.cs @@ -13,7 +13,10 @@ public static partial class SpecificationBuilderExtensions public static IOrderedSpecificationBuilder OrderBy( this ISpecificationBuilder builder, Expression> keySelector) - => OrderBy(builder, keySelector, true); + { + OrderBy((ISpecificationBuilder)builder, keySelector, true); + return (SpecificationBuilder)builder; + } /// /// Adds an OrderBy clause to the specification if the condition is true. @@ -29,7 +32,7 @@ public static IOrderedSpecificationBuilder OrderBy( Expression> keySelector, bool condition) { - ((ISpecificationBuilder)builder).OrderBy(keySelector, condition); + OrderBy((ISpecificationBuilder)builder, keySelector, condition); return (SpecificationBuilder)builder; } @@ -79,7 +82,10 @@ public static IOrderedSpecificationBuilder OrderBy( public static IOrderedSpecificationBuilder OrderByDescending( this ISpecificationBuilder builder, Expression> keySelector) - => OrderByDescending(builder, keySelector, true); + { + OrderByDescending((ISpecificationBuilder)builder, keySelector, true); + return (SpecificationBuilder)builder; + } /// /// Adds an OrderByDescending clause to the specification if the condition is true. @@ -95,7 +101,7 @@ public static IOrderedSpecificationBuilder OrderByDescending> keySelector, bool condition) { - ((ISpecificationBuilder)builder).OrderByDescending(keySelector, condition); + OrderByDescending((ISpecificationBuilder)builder, keySelector, condition); return (SpecificationBuilder)builder; } @@ -145,7 +151,10 @@ public static IOrderedSpecificationBuilder OrderByDescending( public static IOrderedSpecificationBuilder ThenBy( this IOrderedSpecificationBuilder builder, Expression> keySelector) - => ThenBy(builder, keySelector, true); + { + ThenBy((IOrderedSpecificationBuilder)builder, keySelector, true); + return builder; + } /// /// Adds a ThenBy clause to the specification if the condition is true. @@ -161,7 +170,7 @@ public static IOrderedSpecificationBuilder ThenBy( Expression> keySelector, bool condition) { - ((IOrderedSpecificationBuilder)builder).ThenBy(keySelector, condition); + ThenBy((IOrderedSpecificationBuilder)builder, keySelector, condition); return builder; } @@ -214,7 +223,10 @@ public static IOrderedSpecificationBuilder ThenBy( public static IOrderedSpecificationBuilder ThenByDescending( this IOrderedSpecificationBuilder builder, Expression> keySelector) - => ThenByDescending(builder, keySelector, true); + { + ThenByDescending((IOrderedSpecificationBuilder)builder, keySelector, true); + return builder; + } /// /// Adds a ThenByDescending clause to the specification if the condition is true. @@ -230,7 +242,7 @@ public static IOrderedSpecificationBuilder ThenByDescending> keySelector, bool condition) { - ((IOrderedSpecificationBuilder)builder).ThenByDescending(keySelector, condition); + ThenByDescending((IOrderedSpecificationBuilder)builder, keySelector, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Paging.cs b/src/Ardalis.Specification/Builders/Builder_Paging.cs index 83fadc73..e282fee5 100644 --- a/src/Ardalis.Specification/Builders/Builder_Paging.cs +++ b/src/Ardalis.Specification/Builders/Builder_Paging.cs @@ -14,7 +14,10 @@ public static partial class SpecificationBuilderExtensions public static ISpecificationBuilder Take( this ISpecificationBuilder builder, int take) - => Take(builder, take, true); + { + Take((ISpecificationBuilder)builder, take, true); + return builder; + } /// /// Sets the number of items to take in the specification if the condition is true. @@ -31,7 +34,7 @@ public static ISpecificationBuilder Take( int take, bool condition) { - ((ISpecificationBuilder)builder).Take(take, condition); + Take((ISpecificationBuilder)builder, take, condition); return builder; } @@ -83,7 +86,10 @@ public static ISpecificationBuilder Take( public static ISpecificationBuilder Skip( this ISpecificationBuilder builder, int skip) - => Skip(builder, skip, true); + { + Skip((ISpecificationBuilder)builder, skip, true); + return builder; + } /// /// Sets the number of items to skip in the specification if the condition is true. @@ -100,7 +106,7 @@ public static ISpecificationBuilder Skip( int skip, bool condition) { - ((ISpecificationBuilder)builder).Skip(skip, condition); + Skip((ISpecificationBuilder)builder, skip, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Search.cs b/src/Ardalis.Specification/Builders/Builder_Search.cs index 8aae1e85..279b0c09 100644 --- a/src/Ardalis.Specification/Builders/Builder_Search.cs +++ b/src/Ardalis.Specification/Builders/Builder_Search.cs @@ -19,7 +19,10 @@ public static ISpecificationBuilder Search( Expression> keySelector, string pattern, int group = 1) where T : class - => Search(builder, keySelector, pattern, true, group); + { + Search((ISpecificationBuilder)builder, keySelector, pattern, true, group); + return builder; + } /// /// Adds a Like clause to the specification if the condition is true. @@ -39,7 +42,7 @@ public static ISpecificationBuilder Search( bool condition, int group = 1) where T : class { - ((ISpecificationBuilder)builder).Search(keySelector, pattern, condition, group); + Search((ISpecificationBuilder)builder, keySelector, pattern, condition, group); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_TagWith.cs b/src/Ardalis.Specification/Builders/Builder_TagWith.cs index 29a6a3e6..ee29319d 100644 --- a/src/Ardalis.Specification/Builders/Builder_TagWith.cs +++ b/src/Ardalis.Specification/Builders/Builder_TagWith.cs @@ -13,7 +13,10 @@ public static partial class SpecificationBuilderExtensions public static ISpecificationBuilder TagWith( this ISpecificationBuilder builder, string tag) - => TagWith(builder, tag, true); + { + TagWith((ISpecificationBuilder)builder, tag, true); + return builder; + } /// /// Adds a query tag to the specification if the condition is true. @@ -29,7 +32,7 @@ public static ISpecificationBuilder TagWith( string tag, bool condition) { - ((ISpecificationBuilder)builder).TagWith(tag, condition); + TagWith((ISpecificationBuilder)builder, tag, condition); return builder; } diff --git a/src/Ardalis.Specification/Builders/Builder_Where.cs b/src/Ardalis.Specification/Builders/Builder_Where.cs index 8a2a382f..38bb4a66 100644 --- a/src/Ardalis.Specification/Builders/Builder_Where.cs +++ b/src/Ardalis.Specification/Builders/Builder_Where.cs @@ -13,7 +13,10 @@ public static partial class SpecificationBuilderExtensions public static ISpecificationBuilder Where( this ISpecificationBuilder builder, Expression> predicate) - => Where(builder, predicate, true); + { + Where((ISpecificationBuilder)builder, predicate, true); + return builder; + } /// /// Adds a Where clause to the specification if the condition is true. @@ -29,7 +32,7 @@ public static ISpecificationBuilder Where( Expression> predicate, bool condition) { - ((ISpecificationBuilder)builder).Where(predicate, condition); + Where((ISpecificationBuilder)builder, predicate, condition); return builder; } From 5a9ff25f270a0c5002b1a4c1b816d867f17bf1ac Mon Sep 17 00:00:00 2001 From: Fati Iseni Date: Fri, 14 Mar 2025 17:31:49 +0200 Subject: [PATCH 3/3] Clean some Select usages. --- samples/Ardalis.Sample.App2/Program.cs | 17 +++++++++------- .../RepositoryOfT_ListAsync.cs | 4 ++-- .../Extensions_WithSpecification.cs | 12 +++++------ .../QueryTests.cs | 4 ++-- .../Repositories/Repository_AnyTests.cs | 8 ++++---- .../Repositories/Repository_CountTests.cs | 8 ++++---- .../Repositories/Repository_FirstTests.cs | 20 +++++++++---------- .../Repositories/Repository_ListTests.cs | 4 ++-- 8 files changed, 40 insertions(+), 37 deletions(-) diff --git a/samples/Ardalis.Sample.App2/Program.cs b/samples/Ardalis.Sample.App2/Program.cs index 74c80218..0f73647d 100644 --- a/samples/Ardalis.Sample.App2/Program.cs +++ b/samples/Ardalis.Sample.App2/Program.cs @@ -103,11 +103,13 @@ public class CustomerByIdProjectionSpec : Specification { public CustomerByIdProjectionSpec(int id) { - Query.Where(x => x.Id == id); - Query.Select(x => new CustomerDto(x.Id, x.Name, x.Age, - x.Addresses - .Select(a => new AddressDto(a.Id, a.Street, a.CustomerId)) - .ToList())); + Query + .Where(x => x.Id == id) + .Select(x => new CustomerDto( + x.Id, + x.Name, + x.Age, + x.Addresses.Select(a => new AddressDto(a.Id, a.Street, a.CustomerId)).ToList())); } } @@ -115,8 +117,9 @@ public class CustomerNameSpec : Specification { public CustomerNameSpec(int id) { - Query.Where(x => x.Id == id); - Query.Select(x => x.Name); + Query + .Where(x => x.Id == id) + .Select(x => x.Name); } } diff --git a/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_ListAsync.cs b/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_ListAsync.cs index 1f663cd6..8b255ac8 100644 --- a/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_ListAsync.cs +++ b/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_ListAsync.cs @@ -88,8 +88,8 @@ public async Task ReturnsSecondPageOfStoreNames_GivenStoreNamesPaginatedSpec() spec.Query .OrderBy(x => x.Id) .Skip(skip) - .Take(take); - spec.Query.Select(x => x.Name); + .Take(take) + .Select(x => x.Name); var storeNames = await repo.ListAsync(spec); diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Extensions/Extensions_WithSpecification.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Extensions/Extensions_WithSpecification.cs index f8476834..83b10009 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Extensions/Extensions_WithSpecification.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Extensions/Extensions_WithSpecification.cs @@ -84,8 +84,8 @@ public void QueriesMatch_GivenFullQueryWithSelect() .ThenByDescending(x => x.Name) .Skip(1) .Take(10) - .IgnoreQueryFilters(); - spec.Query.Select(x => x.Name); + .IgnoreQueryFilters() + .Select(x => x.Name); var actual = DbContext.Stores .WithSpecification(spec) @@ -142,8 +142,8 @@ public void QueriesMatch_GivenFullQueryWithSelectMany() .ThenByDescending(x => x.Name) .Skip(1) .Take(10) - .IgnoreQueryFilters(); - spec.Query.SelectMany(x => x.Products.Select(x => x.Name)); + .IgnoreQueryFilters() + .SelectMany(x => x.Products.Select(x => x.Name)); var actual = DbContext.Stores .WithSpecification(spec) @@ -204,8 +204,8 @@ public void QueriesMatch_GivenSelectorAndCustomEvaluator() spec.Query .Where(x => x.Id > id) .Skip(1) - .Take(10); - spec.Query.Select(x => new CountryDto(x.Name)); + .Take(10) + .Select(x => new CountryDto(x.Name)); var actual = DbContext.Stores .WithSpecification(spec, new MySpecificationEvaluator()) diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/QueryTests.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/QueryTests.cs index b1acf145..824f4bff 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/QueryTests.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/QueryTests.cs @@ -145,8 +145,8 @@ await SeedRangeAsync( var spec = new Specification(); spec.Query - .Where(x => x.Name == "b"); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == "b") + .Select(x => new CountryDto(x.Name)); var result = await DbContext.Countries .WithSpecification(spec) diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_AnyTests.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_AnyTests.cs index f716b5fb..ca30bf57 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_AnyTests.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_AnyTests.cs @@ -102,8 +102,8 @@ await SeedRangeAsync( var repo = new Repository(DbContext); var spec = new Specification(); spec.Query - .Where(x => x.Name == "b"); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == "b") + .Select(x => new CountryDto(x.Name)); var result = await repo.AnyAsync(spec); @@ -167,8 +167,8 @@ await SeedRangeAsync( spec.Query .Where(x => x.Name == "b") .Skip(3) - .Take(1); - spec.Query.Select(x => new CountryDto(x.Name)); + .Take(1) + .Select(x => new CountryDto(x.Name)); var result = await repo.AnyAsync(spec); diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_CountTests.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_CountTests.cs index bc0ef739..66054d17 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_CountTests.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_CountTests.cs @@ -102,8 +102,8 @@ await SeedRangeAsync( var repo = new Repository(DbContext); var spec = new Specification(); spec.Query - .Where(x => x.Name == "b"); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == "b") + .Select(x => new CountryDto(x.Name)); var result = await repo.CountAsync(spec); @@ -167,8 +167,8 @@ await SeedRangeAsync( spec.Query .Where(x => x.Name == "b") .Skip(1) - .Take(1); - spec.Query.Select(x => new CountryDto(x.Name)); + .Take(1) + .Select(x => new CountryDto(x.Name)); var result = await repo.CountAsync(spec); diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_FirstTests.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_FirstTests.cs index b7969444..ddab7245 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_FirstTests.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_FirstTests.cs @@ -56,8 +56,8 @@ await SeedRangeAsync(new[] var repo = new Repository(DbContext); var spec = new Specification(); spec.Query - .Where(x => x.Name == expected.Name); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == expected.Name) + .Select(x => new CountryDto(x.Name)); var result = await repo.FirstOrDefaultAsync(spec); @@ -73,8 +73,8 @@ public async Task FirstOrDefaultAsync_ReturnsNull_GivenProjectionAndEntityNotExi var repo = new Repository(DbContext); var spec = new Specification(); spec.Query - .Where(x => x.Name == expected.Name); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == expected.Name) + .Select(x => new CountryDto(x.Name)); var result = await repo.FirstOrDefaultAsync(spec); @@ -154,8 +154,8 @@ await SeedRangeAsync(new[] var repo = new Repository(DbContext); var spec = new SingleResultSpecification(); spec.Query - .Where(x => x.Name == expected.Name); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == expected.Name) + .Select(x => new CountryDto(x.Name)); var result = await repo.SingleOrDefaultAsync(spec); @@ -171,8 +171,8 @@ public async Task SingleOrDefaultAsync_ReturnsNull_GivenProjectionAndEntityNotEx var repo = new Repository(DbContext); var spec = new SingleResultSpecification(); spec.Query - .Where(x => x.Name == expected.Name); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == expected.Name) + .Select(x => new CountryDto(x.Name)); var result = await repo.SingleOrDefaultAsync(spec); @@ -194,8 +194,8 @@ await SeedRangeAsync(new[] var repo = new Repository(DbContext); var spec = new SingleResultSpecification(); spec.Query - .Where(x => x.Name == expected.Name); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == expected.Name) + .Select(x => new CountryDto(x.Name)); var result = () => repo.SingleOrDefaultAsync(spec); diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_ListTests.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_ListTests.cs index ccb97144..e1cb5aa1 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_ListTests.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Repositories/Repository_ListTests.cs @@ -74,8 +74,8 @@ await SeedRangeAsync( var repo = new Repository(DbContext); var spec = new Specification(); spec.Query - .Where(x => x.Name == "b"); - spec.Query.Select(x => new CountryDto(x.Name)); + .Where(x => x.Name == "b") + .Select(x => new CountryDto(x.Name)); var result = await repo.ListAsync(spec);