-
Notifications
You must be signed in to change notification settings - Fork 249
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
64 changed files
with
870 additions
and
1,206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net7.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="AutoMapper" Version="12.0.1" /> | ||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" /> | ||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" /> | ||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\Specification.EntityFrameworkCore\src\Ardalis.Specification.EntityFrameworkCore\Ardalis.Specification.EntityFrameworkCore.csproj" /> | ||
<ProjectReference Include="..\Ardalis.Sample.Domain\Ardalis.Sample.Domain.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
using Ardalis.Sample.Domain; | ||
using Ardalis.Sample.Domain.Specs; | ||
using Ardalis.Specification; | ||
using Ardalis.Specification.EntityFrameworkCore; | ||
using AutoMapper; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
|
||
var connectionString = builder.Configuration.GetConnectionString("DbConnection"); | ||
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString)); | ||
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>)); | ||
builder.Services.AddScoped(typeof(IReadRepository<>), typeof(ReadRepository<>)); | ||
|
||
builder.Services.AddAutoMapper(typeof(MappingProfile).Assembly); | ||
builder.Services.AddEndpointsApiExplorer(); | ||
builder.Services.AddSwaggerGen(); | ||
var app = builder.Build(); | ||
app.UseSwagger(); | ||
app.UseSwaggerUI(); | ||
app.UseHttpsRedirection(); | ||
|
||
|
||
app.MapGet("/customers", async (IReadRepository<Customer> repo, IMapper mapper, CancellationToken cancellationToken) => | ||
{ | ||
var spec = new CustomerSpec(); | ||
var customers = await repo.ListAsync(spec, cancellationToken); | ||
var customersDto = mapper.Map<List<CustomerDto>>(customers); | ||
return Results.Ok(customersDto); | ||
}); | ||
|
||
app.MapGet("/customers/{id}", async (IReadRepository<Customer> repo, IMapper mapper, int id, CancellationToken cancellationToken) => | ||
{ | ||
var spec = new CustomerByIdSpec(id); | ||
var customer = await repo.FirstOrDefaultAsync(spec, cancellationToken); | ||
if (customer is null) return Results.NotFound(); | ||
var customerDto = mapper.Map<CustomerDto>(customer); | ||
return Results.Ok(customerDto); | ||
}); | ||
|
||
app.MapPost("/customers", async (IRepository<Customer> repo, IMapper mapper, CustomerCreateDto customerCreateDto, CancellationToken cancellationToken) => | ||
{ | ||
var customer = new Customer | ||
{ | ||
Name = customerCreateDto.Name, | ||
Age = customerCreateDto.Age, | ||
Addresses = customerCreateDto.Addresses.Select(a => new Address { Street = a.Street }).ToList() | ||
}; | ||
await repo.AddAsync(customer, cancellationToken); | ||
var customerDto = mapper.Map<CustomerDto>(customer); | ||
return Results.Ok(customerDto); | ||
}); | ||
|
||
app.MapPut("/customers/{id}", async (IRepository<Customer> repo, IMapper mapper, int id, CustomerUpdateDto customerUpdate, CancellationToken cancellationToken) => | ||
{ | ||
var spec = new CustomerByIdSpec(id); | ||
var customer = await repo.FirstOrDefaultAsync(spec, cancellationToken); | ||
if (customer is null) return Results.NotFound(); | ||
customer.Name = customerUpdate.Name; | ||
customer.Age = customerUpdate.Age; | ||
await repo.UpdateAsync(customer, cancellationToken); | ||
var customerDto = mapper.Map<CustomerDto>(customer); | ||
return Results.Ok(customerDto); | ||
}); | ||
|
||
await app.InitializeDbAsync(); | ||
app.Run(); | ||
|
||
public record AddressDto(int Id, string Street, int CustomerId); | ||
public record AddressCreateDto(string Street); | ||
public record CustomerDto(int Id, string Name, int Age, List<AddressDto> Addresses); | ||
public record CustomerCreateDto(string Name, int Age, List<AddressCreateDto> Addresses); | ||
public record CustomerUpdateDto(string Name, int Age); | ||
|
||
public class AppDbContext : DbContext | ||
{ | ||
public DbSet<Customer> Customers => Set<Customer>(); | ||
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) | ||
{ | ||
} | ||
} | ||
|
||
public interface IRepository<T> : IRepositoryBase<T> where T : class, IAggregateRoot | ||
{ | ||
} | ||
public interface IReadRepository<T> : IReadRepositoryBase<T> where T : class | ||
{ | ||
} | ||
public class Repository<T> : RepositoryBase<T>, IRepository<T> where T : class, IAggregateRoot | ||
{ | ||
public Repository(AppDbContext dbContext) : base(dbContext) | ||
{ | ||
} | ||
} | ||
public class ReadRepository<T> : RepositoryBase<T>, IReadRepository<T> where T : class | ||
{ | ||
public ReadRepository(AppDbContext dbContext) : base(dbContext) | ||
{ | ||
} | ||
} | ||
|
||
public class MappingProfile : Profile | ||
{ | ||
public MappingProfile() | ||
{ | ||
CreateMap<Address, AddressDto>(); | ||
CreateMap<Customer, CustomerDto>(); | ||
} | ||
} | ||
|
||
public static class WebApplicationExtensions | ||
{ | ||
public static async Task InitializeDbAsync(this WebApplication app) | ||
{ | ||
using var scope = app.Services.CreateScope(); | ||
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>(); | ||
await dbContext.Database.EnsureDeletedAsync(); | ||
await dbContext.Database.EnsureCreatedAsync(); | ||
var customers = new List<Customer>() | ||
{ | ||
new() | ||
{ | ||
Name = "Customer1", | ||
Age = 20, | ||
Addresses = new() | ||
{ | ||
new() { Street = "Street1_1" }, | ||
new() { Street = "Street1_2" } | ||
} | ||
}, | ||
new() | ||
{ | ||
Name = "Customer2", | ||
Age = 30, | ||
Addresses = new() | ||
{ | ||
new() { Street = "Street2_1" }, | ||
new() { Street = "Street3_2" } | ||
} | ||
} | ||
}; | ||
dbContext.Customers.AddRange(customers); | ||
await dbContext.SaveChangesAsync(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"ConnectionStrings": { | ||
"DbConnection": "Server=(localdb)\\mssqllocaldb;Database=SpecificationSampleApp1;Trusted_Connection=True;TrustServerCertificate=Yes" | ||
}, | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
}, | ||
"AllowedHosts": "*" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Ardalis.Specification.EntityFrameworkCore; | ||
|
||
namespace Ardalis.Sample.App2; | ||
|
||
public class AppSpecificationEvaluator : SpecificationEvaluator | ||
{ | ||
public static AppSpecificationEvaluator Instance { get; } = new AppSpecificationEvaluator(); | ||
|
||
public AppSpecificationEvaluator() : base() | ||
{ | ||
Evaluators.Add(QueryTagEvaluator.Instance); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net7.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="AutoMapper" Version="12.0.1" /> | ||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" /> | ||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" /> | ||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\Specification.EntityFrameworkCore\src\Ardalis.Specification.EntityFrameworkCore\Ardalis.Specification.EntityFrameworkCore.csproj" /> | ||
<ProjectReference Include="..\Ardalis.Sample.Domain\Ardalis.Sample.Domain.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using Ardalis.Sample.Domain.Filters; | ||
using Ardalis.Specification; | ||
|
||
namespace Ardalis.Sample.App2; | ||
|
||
public interface IReadRepository<T> where T : class | ||
{ | ||
Task<T?> FindAsync<TId>(TId id, CancellationToken cancellationToken = default) where TId : notnull; | ||
Task<T?> FirstOrDefaultAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<TResult?> FirstOrDefaultAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default); | ||
Task<T?> SingleOrDefaultAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<TResult?> SingleOrDefaultAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default); | ||
Task<List<T>> ListAsync(CancellationToken cancellationToken = default); | ||
Task<List<T>> ListAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<List<TResult>> ListAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default); | ||
Task<int> CountAsync(CancellationToken cancellationToken = default); | ||
Task<int> CountAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<bool> AnyAsync(CancellationToken cancellationToken = default); | ||
Task<bool> AnyAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
|
||
Task<TResult?> ProjectToFirstOrDefaultAsync<TResult>(ISpecification<T> specification, CancellationToken cancellationToken); | ||
Task<List<TResult>> ProjectToListAsync<TResult>(ISpecification<T> specification, CancellationToken cancellationToken); | ||
Task<PagedResponse<TResult>> ProjectToListAsync<TResult>(ISpecification<T> specification, BaseFilter filter, CancellationToken cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using Ardalis.Sample.Domain; | ||
using Ardalis.Specification; | ||
|
||
namespace Ardalis.Sample.App2; | ||
|
||
public interface IRepository<T> where T : class, IAggregateRoot | ||
{ | ||
Task<T> AddAsync(T entity, CancellationToken cancellationToken = default); | ||
Task<IEnumerable<T>> AddRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default); | ||
Task UpdateAsync(T entity, CancellationToken cancellationToken = default); | ||
Task DeleteAsync(T entity, CancellationToken cancellationToken = default); | ||
Task DeleteRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default); | ||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default); | ||
|
||
Task<T?> FindAsync<TId>(TId id, CancellationToken cancellationToken = default) where TId : notnull; | ||
Task<T?> FirstOrDefaultAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<TResult?> FirstOrDefaultAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default); | ||
Task<T?> SingleOrDefaultAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<TResult?> SingleOrDefaultAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default); | ||
Task<List<T>> ListAsync(CancellationToken cancellationToken = default); | ||
Task<List<T>> ListAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<List<TResult>> ListAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default); | ||
Task<int> CountAsync(CancellationToken cancellationToken = default); | ||
Task<int> CountAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
Task<bool> AnyAsync(CancellationToken cancellationToken = default); | ||
Task<bool> AnyAsync(ISpecification<T> specification, CancellationToken cancellationToken = default); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
namespace Ardalis.Sample.App2; | ||
|
||
public class PagedResponse<T> | ||
{ | ||
public Pagination Pagination { get; } | ||
public List<T> Data { get; } | ||
|
||
public PagedResponse(List<T> data, Pagination pagination) | ||
{ | ||
Data = data; | ||
Pagination = pagination; | ||
} | ||
} | ||
|
Oops, something went wrong.