diff --git a/src/Ardalis.Specification.EntityFrameworkCore/Evaluators/SpecificationEvaluator.cs b/src/Ardalis.Specification.EntityFrameworkCore/Evaluators/SpecificationEvaluator.cs index 1d909237..150c266c 100644 --- a/src/Ardalis.Specification.EntityFrameworkCore/Evaluators/SpecificationEvaluator.cs +++ b/src/Ardalis.Specification.EntityFrameworkCore/Evaluators/SpecificationEvaluator.cs @@ -40,7 +40,7 @@ public SpecificationEvaluator(IEnumerable evaluators) /// public virtual IQueryable GetQuery(IQueryable query, ISpecification specification) where T : class { - if (specification is null) throw new ArgumentNullException(nameof(specification)); + ArgumentNullException.ThrowIfNull(specification); if (specification.Selector is null && specification.SelectorMany is null) throw new SelectorNotFoundException(); if (specification.Selector is not null && specification.SelectorMany is not null) throw new ConcurrentSelectorsException(); @@ -54,7 +54,7 @@ public virtual IQueryable GetQuery(IQueryable query, ISp /// public virtual IQueryable GetQuery(IQueryable query, ISpecification specification, bool evaluateCriteriaOnly = false) where T : class { - if (specification is null) throw new ArgumentNullException(nameof(specification)); + ArgumentNullException.ThrowIfNull(specification); var evaluators = evaluateCriteriaOnly ? Evaluators.Where(x => x.IsCriteriaEvaluator) : Evaluators; diff --git a/src/Ardalis.Specification/Builders/SpecificationBuilder.cs b/src/Ardalis.Specification/Builders/SpecificationBuilder.cs index 718cc3c4..65f34ecd 100644 --- a/src/Ardalis.Specification/Builders/SpecificationBuilder.cs +++ b/src/Ardalis.Specification/Builders/SpecificationBuilder.cs @@ -37,7 +37,7 @@ internal class SpecificationBuilder : SpecificationBuilder, public new Specification Specification { get; } public SpecificationBuilder(Specification specification) - :base(specification) + : base(specification) { Specification = specification; } diff --git a/src/Ardalis.Specification/IncludeTypeEnum.cs b/src/Ardalis.Specification/Expressions/IncludeTypeEnum.cs similarity index 100% rename from src/Ardalis.Specification/IncludeTypeEnum.cs rename to src/Ardalis.Specification/Expressions/IncludeTypeEnum.cs diff --git a/src/Ardalis.Specification/OrderTypeEnum.cs b/src/Ardalis.Specification/Expressions/OrderTypeEnum.cs similarity index 100% rename from src/Ardalis.Specification/OrderTypeEnum.cs rename to src/Ardalis.Specification/Expressions/OrderTypeEnum.cs diff --git a/src/Ardalis.Specification/CollectionExtensions.cs b/src/Ardalis.Specification/Internals/CollectionExtensions.cs similarity index 100% rename from src/Ardalis.Specification/CollectionExtensions.cs rename to src/Ardalis.Specification/Internals/CollectionExtensions.cs diff --git a/src/Ardalis.Specification/Specification.cs b/src/Ardalis.Specification/Specification.cs index d59e7221..84381817 100644 --- a/src/Ardalis.Specification/Specification.cs +++ b/src/Ardalis.Specification/Specification.cs @@ -26,8 +26,6 @@ public class Specification : Specification, ISpecification public class Specification : ISpecification { - private const int DEFAULT_CAPACITY_SEARCH = 2; - // It is utilized only during the building stage for the sub-chains. Once the state is built, we don't care about it anymore. // The initial value is not important since the value is always initialized by the root of the chain. // Therefore, we don't need ThreadLocal (it's more expensive). @@ -43,8 +41,8 @@ public class Specification : ISpecification private OneOrMany> _orderExpressions = new(); private OneOrMany _includeExpressions = new(); private OneOrMany _includeStrings = new(); - private Dictionary? _items; private OneOrMany _queryTags = new(); + private Dictionary? _items; public ISpecificationBuilder Query => new SpecificationBuilder(this); protected virtual IInMemorySpecificationEvaluator Evaluator => InMemorySpecificationEvaluator.Default; @@ -88,15 +86,6 @@ public class Specification : ISpecification /// public bool AsNoTrackingWithIdentityResolution { get; internal set; } = false; - - // Specs are not intended to be thread-safe, so we don't need to worry about thread-safety here. - internal void Add(WhereExpressionInfo whereExpression) => _whereExpressions.Add(whereExpression); - internal void Add(OrderExpressionInfo orderExpression) => _orderExpressions.Add(orderExpression); - internal void Add(IncludeExpressionInfo includeExpression) => _includeExpressions.Add(includeExpression); - internal void Add(string includeString) => _includeStrings.Add(includeString); - internal void Add(SearchExpressionInfo searchExpression) => _searchExpressions.AddSorted(searchExpression, SearchExpressionComparer.Default); - internal void AddQueryTag(string queryTag) => _queryTags.Add(queryTag); - /// public Dictionary Items => _items ??= []; @@ -118,13 +107,6 @@ public class Specification : ISpecification /// public IEnumerable QueryTags => _queryTags.Values; - internal OneOrMany> OneOrManyWhereExpressions => _whereExpressions; - internal OneOrMany> OneOrManySearchExpressions => _searchExpressions; - internal OneOrMany> OneOrManyOrderExpressions => _orderExpressions; - internal OneOrMany OneOrManyIncludeExpressions => _includeExpressions; - internal OneOrMany OneOrManyIncludeStrings => _includeStrings; - internal OneOrMany OneOrManyQueryTags => _queryTags; - /// public virtual IEnumerable Evaluate(IEnumerable entities) { @@ -139,6 +121,20 @@ public virtual bool IsSatisfiedBy(T entity) return validator.IsValid(entity, this); } + internal OneOrMany> OneOrManyWhereExpressions => _whereExpressions; + internal OneOrMany> OneOrManySearchExpressions => _searchExpressions; + internal OneOrMany> OneOrManyOrderExpressions => _orderExpressions; + internal OneOrMany OneOrManyIncludeExpressions => _includeExpressions; + internal OneOrMany OneOrManyIncludeStrings => _includeStrings; + internal OneOrMany OneOrManyQueryTags => _queryTags; + + internal void Add(WhereExpressionInfo whereExpression) => _whereExpressions.Add(whereExpression); + internal void Add(SearchExpressionInfo searchExpression) => _searchExpressions.AddSorted(searchExpression, SearchExpressionComparer.Default); + internal void Add(OrderExpressionInfo orderExpression) => _orderExpressions.Add(orderExpression); + internal void Add(IncludeExpressionInfo includeExpression) => _includeExpressions.Add(includeExpression); + internal void Add(string includeString) => _includeStrings.Add(includeString); + internal void AddQueryTag(string queryTag) => _queryTags.Add(queryTag); + internal Specification Clone() { var newSpec = new Specification(); diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 78eae77d..e62dd261 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -36,9 +36,9 @@ - - - + + + diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Evaluators/SearchExtensionTests.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Evaluators/SearchExtensionTests.cs index 622ce1aa..34cb8ce4 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Evaluators/SearchExtensionTests.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Evaluators/SearchExtensionTests.cs @@ -54,8 +54,6 @@ public void QueriesMatch_GivenMultipleSearchAsEnumerable() [Fact] public void QueriesMatch_GivenEmptyAsSpan() { - var spec = new Specification(); - var array = Array.Empty>(); var actual = DbContext.Stores @@ -71,8 +69,6 @@ public void QueriesMatch_GivenEmptyAsSpan() [Fact] public void QueriesMatch_GivenEmptyAsEnumerable() { - var spec = new Specification(); - var array = Array.Empty>(); var actual = DbContext.Stores diff --git a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Fixture/TestFactory.cs b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Fixture/TestFactory.cs index a5e3e4ce..5e8b2abb 100644 --- a/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Fixture/TestFactory.cs +++ b/tests/Ardalis.Specification.EntityFrameworkCore.Tests/Fixture/TestFactory.cs @@ -7,7 +7,7 @@ namespace Tests.Fixture; public class TestFactory : IAsyncLifetime { // Flag to force using Docker SQL Server. Update it manually if you want to avoid localDb locally. - private const bool _forceDocker = false; + private const bool FORCE_DOCKER = false; private string _connectionString = default!; private Respawner _respawner = default!; @@ -21,7 +21,7 @@ public async Task InitializeAsync() { using (var localDB = new SqlLocalDbApi()) { - if (_forceDocker || !localDB.IsLocalDBInstalled()) + if (FORCE_DOCKER || !localDB.IsLocalDBInstalled()) { _dbContainer = CreateContainer(); await _dbContainer.StartAsync();