diff --git a/Specification.EntityFrameworkCore/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs b/Specification.EntityFrameworkCore/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs index fbc4d75a..d9ce6b80 100644 --- a/Specification.EntityFrameworkCore/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs +++ b/Specification.EntityFrameworkCore/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs @@ -173,6 +173,12 @@ public virtual async Task AnyAsync(CancellationToken cancellationToken = d return await dbContext.Set().AnyAsync(cancellationToken); } + /// + public virtual IAsyncEnumerable AsAsyncEnumerable(ISpecification specification) + { + return ApplySpecification(specification, true).AsAsyncEnumerable(); + } + /// /// Filters the entities of , to those that match the encapsulated query logic of the /// . diff --git a/Specification.EntityFrameworkCore/tests/Ardalis.Specification.EntityFrameworkCore.IntegrationTests/RepositoryOfT_AsAsyncEnumerable.cs b/Specification.EntityFrameworkCore/tests/Ardalis.Specification.EntityFrameworkCore.IntegrationTests/RepositoryOfT_AsAsyncEnumerable.cs new file mode 100644 index 00000000..9825bea7 --- /dev/null +++ b/Specification.EntityFrameworkCore/tests/Ardalis.Specification.EntityFrameworkCore.IntegrationTests/RepositoryOfT_AsAsyncEnumerable.cs @@ -0,0 +1,56 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Ardalis.Specification.EntityFrameworkCore.IntegrationTests.Fixture; +using Ardalis.Specification.UnitTests.Fixture.Specs; +using FluentAssertions; +using Xunit; + +namespace Ardalis.Specification.EntityFrameworkCore.IntegrationTests +{ + public class RepositoryOfT_AsAsyncEnumerable : RepositoryOfT_AnyAsync_TestKit + { + public RepositoryOfT_AsAsyncEnumerable(SharedDatabaseFixture fixture) + : base(fixture, SpecificationEvaluator.Default) + { + } + } + + public abstract class RepositoryOfT_AsAsyncEnumerable_TestKit : IntegrationTestBase + { + protected RepositoryOfT_AsAsyncEnumerable_TestKit(SharedDatabaseFixture fixture, ISpecificationEvaluator specificationEvaluator) + : base(fixture, specificationEvaluator) + { + } + + [Fact] + public virtual async Task ReturnsTrueOnStoresRecords_WithoutSpec() + { + var results = storeRepository.AsAsyncEnumerable(new StoreIncludeProductsSpec()); + + await foreach (var result in results.WithCancellation(CancellationToken.None)) + { + result.Should().NotBeNull(); + result.Products.Should().NotBeEmpty(); + } + } + + [Fact] + public virtual async Task ReturnsStoreWithIdFrom15To30_GivenStoresByIdAsAsyncEnumerableSpec() + { + var ids = Enumerable.Range(15, 16); + var spec = new StoresByIdListSpec(ids); + + int counter = 0; + var results = storeRepository.AsAsyncEnumerable(spec); + await foreach (var result in results.WithCancellation(CancellationToken.None)) + { + result.Should().NotBeNull(); + result.Products.Should().NotBeEmpty(); + ++counter; + } + + counter.Should().Be(16); + } + } +} diff --git a/Specification/src/Ardalis.Specification/Ardalis.Specification.csproj b/Specification/src/Ardalis.Specification/Ardalis.Specification.csproj index 893dca90..281a5f76 100644 --- a/Specification/src/Ardalis.Specification/Ardalis.Specification.csproj +++ b/Specification/src/Ardalis.Specification/Ardalis.Specification.csproj @@ -33,6 +33,7 @@ + diff --git a/Specification/src/Ardalis.Specification/IReadRepositoryBase.cs b/Specification/src/Ardalis.Specification/IReadRepositoryBase.cs index ab3f3138..14f639cd 100644 --- a/Specification/src/Ardalis.Specification/IReadRepositoryBase.cs +++ b/Specification/src/Ardalis.Specification/IReadRepositoryBase.cs @@ -166,5 +166,18 @@ public interface IReadRepositoryBase where T : class /// source sequence contains any elements; otherwise, false. /// Task AnyAsync(CancellationToken cancellationToken = default); + + +#if !NETSTANDARD2_0 + /// + /// Finds all entities of , that matches the encapsulated query logic of the + /// , from the database. + /// + /// The encapsulated query logic. + /// + /// Returns an IAsyncEnumerable which can be enumerated asynchronously. + /// + IAsyncEnumerable AsAsyncEnumerable(ISpecification specification); +#endif } }