update solution to implement services, repository and unit of work
This commit is contained in:
parent
26c8922752
commit
3a26c007d2
23
src/UserManager.API/Controllers/UserController.cs
Normal file
23
src/UserManager.API/Controllers/UserController.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using UserManager.Application.Features.Users.Interfaces;
|
||||
using UserManager.Application.Features.Users.Requests;
|
||||
using UserManager.Application.Features.Users.Responses;
|
||||
|
||||
namespace UserManager.API.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class UserController(ILogger<UserController> logger, IUserService userService) : ControllerBase
|
||||
{
|
||||
private readonly ILogger<UserController> _logger = logger;
|
||||
private readonly IUserService _userService = userService;
|
||||
|
||||
[HttpPost(Name = "CreateUser")]
|
||||
public async Task<ActionResult<CreateUserResponseDto>> CreateUserAsync(CreateUserRequestDto request)
|
||||
{
|
||||
_logger.LogInformation("Creating user with first name {FirstName} and last name {LastName}", request.FirstName, request.LastName);
|
||||
CreateUserResponseDto response = await _userService.CreateUserAsync(request);
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace UserManager.API.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class WeatherForecastController : ControllerBase
|
||||
{
|
||||
private static readonly string[] Summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
|
||||
private readonly ILogger<WeatherForecastController> _logger;
|
||||
|
||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet(Name = "GetWeatherForecast")]
|
||||
public IEnumerable<WeatherForecast> Get()
|
||||
{
|
||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,11 @@
|
||||
using UserManager.Application;
|
||||
using UserManager.Infrastructure;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddApplication();
|
||||
builder.Services.AddInfrastructure(builder.Configuration);
|
||||
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
|
@ -7,7 +7,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.10">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\UserManager.Application\UserManager.Application.csproj" />
|
||||
<ProjectReference Include="..\UserManager.Infrastructure\UserManager.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,6 +0,0 @@
|
||||
@UserManager.API_HostAddress = http://localhost:5110
|
||||
|
||||
GET {{UserManager.API_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
@ -1,13 +0,0 @@
|
||||
namespace UserManager.API
|
||||
{
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
|
||||
public string? Summary { get; set; }
|
||||
}
|
||||
}
|
@ -4,5 +4,8 @@
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"UserManagerContext": "Server=localhost;Port=5432;Database=user-manager;User Id=postgres;Password=postgres;"
|
||||
}
|
||||
}
|
||||
|
14
src/UserManager.Application/DependancyInjection.cs
Normal file
14
src/UserManager.Application/DependancyInjection.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using UserManager.Application.Features.Users.Interfaces;
|
||||
using UserManager.Application.Features.Users.Services;
|
||||
|
||||
namespace UserManager.Application
|
||||
{
|
||||
public static class DependancyInjection
|
||||
{
|
||||
public static void AddApplication(this IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
{
|
||||
public class CreateUserResponseDto
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,32 @@
|
||||
using UserManager.Application.Features.Users.Requests;
|
||||
using UserManager.Application.Features.Users.Responses;
|
||||
using UserManager.Application.Interfaces;
|
||||
using UserManager.Domain.Entities;
|
||||
|
||||
namespace UserManager.Application.Features.Users.Services
|
||||
{
|
||||
class UserService(IUserRepository userRepository) : IUserService
|
||||
class UserService(IUnitOfWork unitOfWork) : IUserService
|
||||
{
|
||||
private readonly IUserRepository _userRepository = userRepository;
|
||||
private readonly IUnitOfWork _unitOfWork = unitOfWork;
|
||||
|
||||
public Task<CreateUserResponseDto> CreateUserAsync(CreateUserRequestDto request)
|
||||
public async Task<CreateUserResponseDto> CreateUserAsync(CreateUserRequestDto request)
|
||||
{
|
||||
// TODO
|
||||
// First validate this user does not exist
|
||||
// Then create the user
|
||||
User user = new()
|
||||
{
|
||||
FirstName = request.FirstName,
|
||||
LastName = request.LastName,
|
||||
};
|
||||
|
||||
await _unitOfWork.UserRepository.CreateAsync(user);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
|
||||
return new CreateUserResponseDto()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
FirstName = user.FirstName,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
src/UserManager.Application/Interfaces/IUnitOfWork.cs
Normal file
8
src/UserManager.Application/Interfaces/IUnitOfWork.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace UserManager.Application.Interfaces
|
||||
{
|
||||
public interface IUnitOfWork
|
||||
{
|
||||
IUserRepository UserRepository { get; }
|
||||
Task<int> SaveChangesAsync();
|
||||
}
|
||||
}
|
@ -10,6 +10,10 @@
|
||||
<Folder Include="Features\Restaurants\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\UserManager.Domain\UserManager.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
16
src/UserManager.Infrastructure/BaseRepository.cs
Normal file
16
src/UserManager.Infrastructure/BaseRepository.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using UserManager.Application.Interfaces;
|
||||
|
||||
namespace UserManager.Infrastructure
|
||||
{
|
||||
public class BaseRepository<TEntity>(UserManagerContext context) : IBaseRepository<TEntity> where TEntity : class
|
||||
{
|
||||
private readonly UserManagerContext _context = context;
|
||||
private readonly DbSet<TEntity> _dbSet = context.Set<TEntity>();
|
||||
|
||||
public async Task CreateAsync(TEntity entity)
|
||||
{
|
||||
await _dbSet.AddAsync(entity);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace UserManager.Infrastructure
|
||||
{
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
}
|
19
src/UserManager.Infrastructure/DependancyInjection.cs
Normal file
19
src/UserManager.Infrastructure/DependancyInjection.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using UserManager.Application.Interfaces;
|
||||
|
||||
namespace UserManager.Infrastructure
|
||||
{
|
||||
public static class DependancyInjection
|
||||
{
|
||||
public static void AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddDbContext<UserManagerContext>(options =>
|
||||
options.UseNpgsql(configuration.GetConnectionString(nameof(UserManagerContext))));
|
||||
|
||||
services.AddScoped<IUserRepository, UserRepository>();
|
||||
services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||
}
|
||||
}
|
||||
}
|
50
src/UserManager.Infrastructure/Migrations/20241022053245_Added Users.Designer.cs
generated
Normal file
50
src/UserManager.Infrastructure/Migrations/20241022053245_Added Users.Designer.cs
generated
Normal file
@ -0,0 +1,50 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using UserManager.Infrastructure;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UserManager.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(UserManagerContext))]
|
||||
[Migration("20241022053245_Added Users")]
|
||||
partial class AddedUsers
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.10")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("UserManager.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("UserId"));
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UserManager.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedUsers : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
FirstName = table.Column<string>(type: "text", nullable: false),
|
||||
LastName = table.Column<string>(type: "text", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.UserId);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using UserManager.Infrastructure;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UserManager.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(UserManagerContext))]
|
||||
partial class UserManagerContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.10")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("UserManager.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("UserId"));
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
15
src/UserManager.Infrastructure/UnitOfWork.cs
Normal file
15
src/UserManager.Infrastructure/UnitOfWork.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using UserManager.Application.Interfaces;
|
||||
|
||||
namespace UserManager.Infrastructure
|
||||
{
|
||||
public class UnitOfWork(UserManagerContext context) : IUnitOfWork
|
||||
{
|
||||
private IUserRepository? _userRepository = null;
|
||||
public IUserRepository UserRepository => _userRepository ??= new UserRepository(context);
|
||||
|
||||
public async Task<int> SaveChangesAsync()
|
||||
{
|
||||
return await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
@ -6,4 +6,20 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\UserManager.Application\UserManager.Application.csproj" />
|
||||
<ProjectReference Include="..\UserManager.Domain\UserManager.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
10
src/UserManager.Infrastructure/UserManagerContext.cs
Normal file
10
src/UserManager.Infrastructure/UserManagerContext.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using UserManager.Domain.Entities;
|
||||
|
||||
namespace UserManager.Infrastructure
|
||||
{
|
||||
public class UserManagerContext(DbContextOptions<UserManagerContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<User> Users { get; set; }
|
||||
}
|
||||
}
|
7
src/UserManager.Infrastructure/UserRepository.cs
Normal file
7
src/UserManager.Infrastructure/UserRepository.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using UserManager.Application.Interfaces;
|
||||
using UserManager.Domain.Entities;
|
||||
|
||||
namespace UserManager.Infrastructure
|
||||
{
|
||||
public class UserRepository(UserManagerContext context) : BaseRepository<User>(context), IUserRepository { }
|
||||
}
|
Loading…
Reference in New Issue
Block a user