diff --git a/CleanArchitecture/.dockerignore b/CleanArchitecture/.dockerignore new file mode 100644 index 0000000..4d72b4f --- /dev/null +++ b/CleanArchitecture/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/CleanArchitecture/CleanArchitecture.API/CleanArchitecture.API.csproj b/CleanArchitecture/CleanArchitecture.API/CleanArchitecture.API.csproj index c854523..98d1f5a 100644 --- a/CleanArchitecture/CleanArchitecture.API/CleanArchitecture.API.csproj +++ b/CleanArchitecture/CleanArchitecture.API/CleanArchitecture.API.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + Linux @@ -11,7 +12,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + + diff --git a/CleanArchitecture/CleanArchitecture.API/Controllers/DirectorController.cs b/CleanArchitecture/CleanArchitecture.API/Controllers/DirectorController.cs new file mode 100644 index 0000000..3b05a98 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.API/Controllers/DirectorController.cs @@ -0,0 +1,28 @@ +using CleanArchitecture.Application.Features.Directors.Commands.CreateDirector; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace CleanArchitecture.API.Controllers +{ + [Route("api/v1/[controller]")] + [ApiController] + public class DirectorController : ControllerBase + { + private IMediator mediator; + + public DirectorController(IMediator mediator) + { + this.mediator = mediator; + } + + [HttpPost(Name = "CreateDirector")] + [Authorize(Roles ="Administrator")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> Create([FromBody] CreateDirectorCommand createDirectorCommand) + { + var response = await mediator.Send(createDirectorCommand); + return Ok(new { directorId = response }); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs b/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs index 1128e83..80547c1 100644 --- a/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs +++ b/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs @@ -25,7 +25,7 @@ namespace CleanArchitecture.API.Controllers public async Task> CreateStreamer([FromBody] CreateStreamerCommand command) { var response = await mediator.Send(command); - return Ok(new { StreamerId = response }); + return Ok(response); } [HttpPut(Name = "UpdateStreamer")] @@ -35,8 +35,8 @@ namespace CleanArchitecture.API.Controllers [ProducesDefaultResponseType] public async Task UpdateStreamer([FromBody] UpdateStreamerCommand command) { - await mediator.Send(command); - return NoContent(); + var createdStreamer = await mediator.Send(command); + return Ok(createdStreamer); } [HttpDelete("{id}", Name = "DeleteStreamer")] @@ -44,7 +44,7 @@ namespace CleanArchitecture.API.Controllers [ProducesResponseType((int)HttpStatusCode.NoContent)] [ProducesResponseType((int)HttpStatusCode.NotFound)] [ProducesDefaultResponseType] - public async Task DeleteStreamer(int id) + public async Task DeleteStreamer(Guid id) { var request = new DeleteStreamerCommand() { Id = id }; await mediator.Send(request); diff --git a/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs b/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs index c5a464b..54caf39 100644 --- a/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs +++ b/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs @@ -1,4 +1,11 @@ -using CleanArchitecture.Application.Features.Videos.Queries.GetVideosList; +using CleanArchitecture.Application.Features.Streamers.Commands.CreateStreamer; +using CleanArchitecture.Application.Features.Streamers.Commands.DeleteStreamer; +using CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer; +using CleanArchitecture.Application.Features.Videos.Commands.CreateVideo; +using CleanArchitecture.Application.Features.Videos.Commands.DeleteVideo; +using CleanArchitecture.Application.Features.Videos.Commands.UpdateVideo; +using CleanArchitecture.Application.Features.Videos.Queries.GetVideosList; +using CleanArchitecture.Domain; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -27,5 +34,37 @@ namespace CleanArchitecture.API.Controllers var videos = await mediator.Send(query); return Ok(videos); } + + [HttpPost(Name = "CreateVideo")] + [Authorize(Roles = "Administrator")] + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + public async Task> CreateVideo([FromBody] CreateVideoCommand command) + { + var response = await mediator.Send(command); + return Ok(response); + } + + [HttpPut(Name = "UpdateVideo")] + [Authorize(Roles = "Administrator")] + [ProducesResponseType((int)HttpStatusCode.NoContent)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesDefaultResponseType] + public async Task> UpdateVideo([FromBody] UpdateVideoCommand command) + { + var response = await mediator.Send(command); + return Ok(response); + } + + [HttpDelete("{id}", Name = "DeleteVideo")] + [Authorize(Roles = "Administrator")] + [ProducesResponseType((int)HttpStatusCode.NoContent)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesDefaultResponseType] + public async Task DeleteVideo(Guid id) + { + var request = new DeleteVideoCommand() { Id = id }; + await mediator.Send(request); + return NoContent(); + } } } diff --git a/CleanArchitecture/CleanArchitecture.API/Dockerfile b/CleanArchitecture/CleanArchitecture.API/Dockerfile new file mode 100644 index 0000000..3d016a6 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.API/Dockerfile @@ -0,0 +1,28 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["CleanArchitecture.API/CleanArchitecture.API.csproj", "CleanArchitecture.API/"] +COPY ["CleanArchitecture.Application/CleanArchitecture.Application.csproj", "CleanArchitecture.Application/"] +COPY ["CleanArchitecture.Domain/CleanArchitecture.Domain.csproj", "CleanArchitecture.Domain/"] +COPY ["CleanArchitecture.Data/CleanArchitecture.Infrastructure.csproj", "CleanArchitecture.Data/"] +COPY ["CleanArchitecture.Identity/CleanArchitecture.Identity.csproj", "CleanArchitecture.Identity/"] +RUN dotnet restore "./CleanArchitecture.API/CleanArchitecture.API.csproj" +COPY . . +WORKDIR "/src/CleanArchitecture.API" +RUN dotnet build "./CleanArchitecture.API.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./CleanArchitecture.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "CleanArchitecture.API.dll"] diff --git a/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json b/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json index 88c1e6c..b3ae0a7 100644 --- a/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json +++ b/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json @@ -1,23 +1,14 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:32905", - "sslPort": 0 - } - }, +{ "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "http://localhost:5124", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:14563" }, "IIS Express": { "commandName": "IISExpress", @@ -26,6 +17,24 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_HTTP_PORTS": "80" + }, + "publishAllPorts": true + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:22080", + "sslPort": 0 } } -} +} \ No newline at end of file diff --git a/CleanArchitecture/CleanArchitecture.API/appsettings.json b/CleanArchitecture/CleanArchitecture.API/appsettings.json index 7ec6057..351455a 100644 --- a/CleanArchitecture/CleanArchitecture.API/appsettings.json +++ b/CleanArchitecture/CleanArchitecture.API/appsettings.json @@ -1,7 +1,7 @@ { "ConnectionStrings": { - "ConnectionString": "server=localhost;database=CleanArchitecture;user=root;password=securePassword", + "ConnectionString": "server=localhost;database=CleanArchitectureV2;user=root;password=securePassword", "IdentityConnectionString": "server=localhost;database=CleanArchitecture.Security;user=root;password=securePassword" }, "EmailSettings": { diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/CleanArchitecture.Application.UnitTests.csproj b/CleanArchitecture/CleanArchitecture.Application.UnitTests/CleanArchitecture.Application.UnitTests.csproj new file mode 100644 index 0000000..2416138 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/CleanArchitecture.Application.UnitTests.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommandHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommandHandlerXUnitTests.cs new file mode 100644 index 0000000..533ca72 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommandHandlerXUnitTests.cs @@ -0,0 +1,51 @@ +using AutoMapper; +using CleanArchitecture.Application.Contracts.Infrastructure; +using CleanArchitecture.Application.Features.Videos.Queries.GetVideosList; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Infrastructure.Repositories; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; +using CleanArchitecture.Application.Features.Streamers.Commands.CreateStreamer; +using Shouldly; +using CleanArchitecture.Domain; +using CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer; + +namespace CleanArchitecture.Application.UnitTests.Features.Streamers.Commands.CreateStreamer +{ + public class CreateStreamerCommandHandlerXUnitTests + { + private readonly IMapper mapper; + private readonly Mock mockUnitOfWork; + private readonly Mock emailService; + private readonly Mock> logger; + + public CreateStreamerCommandHandlerXUnitTests() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + emailService = new Mock(); + logger = new Mock>(); + } + + [Fact] + public async Task CreateStreamerTest() + { + var handler = new CreateStreamerCommandHandler(mockUnitOfWork.Object, mapper, emailService.Object, logger.Object); + var request = new CreateStreamerCommand() + { + Nombre = "AlexStream", + Url = "https://AlexStream.com" + }; + var result = await handler.Handle(request, CancellationToken.None); + + result.ShouldBeOfType(); + result.Nombre.ShouldBe("AlexStream"); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandlerXUnitTests.cs new file mode 100644 index 0000000..69aaa67 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandlerXUnitTests.cs @@ -0,0 +1,52 @@ +using AutoMapper; +using CleanArchitecture.Application.Contracts.Infrastructure; +using CleanArchitecture.Application.Features.Streamers.Commands.DeleteStreamer; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Domain; +using CleanArchitecture.Infrastructure.Repositories; +using Microsoft.Extensions.Logging; +using Moq; +using Shouldly; +using Xunit; + +namespace CleanArchitecture.Application.UnitTests.Features.Streamers.Commands.DeleteStreamer +{ + public class DeleteVideoCommandHandlerXUnitTests + { + private readonly IMapper mapper; + private readonly Mock mockUnitOfWork; + private readonly Mock emailService; + private readonly Mock> logger; + + public DeleteVideoCommandHandlerXUnitTests() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + emailService = new Mock(); + logger = new Mock>(); + + MockStreamerRepository.AddDataStreamerRepository(mockUnitOfWork.Object.StreamerDbContext); + } + + [Fact] + public async Task UpdateStreamerTest() + { + var handler = new DeleteStreamerCommandHandler(mockUnitOfWork.Object, mapper, logger.Object); + var request = new DeleteStreamerCommand() + { + Id = Guid.Parse("edfe00d5-7599-4788-b52a-acc2a683b188") + }; + MediatR.Unit result = await handler.Handle(request, CancellationToken.None); + if (result == null) + { + throw new Exception("Result is null"); + } + result.ShouldBeOfType(); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommandHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommandHandlerXUnitTests.cs new file mode 100644 index 0000000..abaec48 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommandHandlerXUnitTests.cs @@ -0,0 +1,61 @@ +using AutoMapper; +using CleanArchitecture.Application.Contracts.Infrastructure; + +using CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Domain; +using CleanArchitecture.Infrastructure.Repositories; +using Microsoft.Extensions.Logging; +using Moq; +using Shouldly; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace CleanArchitecture.Application.UnitTests.Features.Streamers.Commands.UpdateStreamer +{ + public class UpdateStreamerCommandHandlerXUnitTests + { + private readonly IMapper mapper; + private readonly Mock mockUnitOfWork; + private readonly Mock emailService; + private readonly Mock> logger; + + public UpdateStreamerCommandHandlerXUnitTests() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + emailService = new Mock(); + logger = new Mock>(); + + MockStreamerRepository.AddDataStreamerRepository(mockUnitOfWork.Object.StreamerDbContext); + } + + [Fact] + public async Task UpdateStreamerTest() + { + var handler = new UpdateStreamerCommandHandler(mockUnitOfWork.Object, mapper, logger.Object); + var request = new UpdateStreamerCommand() + { + Id = Guid.Parse("edfe00d5-7599-4788-b52a-acc2a683b188"), + Nombre = "AlexStream2", + Url = "https://AlexStream2.com" + }; + var result = await handler.Handle(request, CancellationToken.None); + if(result == null) + { + throw new Exception("Result is null"); + } + result.ShouldBeOfType(); + result.Nombre.ShouldBe("AlexStream2"); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/CreateVideo/CreateVideoCommandHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/CreateVideo/CreateVideoCommandHandlerXUnitTests.cs new file mode 100644 index 0000000..f6426c2 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/CreateVideo/CreateVideoCommandHandlerXUnitTests.cs @@ -0,0 +1,49 @@ +using AutoMapper; +using CleanArchitecture.Application.Contracts.Infrastructure; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Infrastructure.Repositories; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; +using Shouldly; +using CleanArchitecture.Application.Features.Videos.Commands.CreateVideo; + +namespace CleanArchitecture.Application.UnitTests.Features.Videos.Commands.CreateStreamer +{ + public class CreateVideoCommandHandlerXUnitTests + { + private readonly IMapper mapper; + private readonly Mock mockUnitOfWork; + private readonly Mock emailService; + private readonly Mock> logger; + + public CreateVideoCommandHandlerXUnitTests() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + emailService = new Mock(); + logger = new Mock>(); + } + + [Fact] + public async Task CreateVideoTest() + { + + + var handler = new CreateVideoCommandHandler(mockUnitOfWork.Object, mapper, emailService.Object, logger.Object); + var request = new CreateVideoCommand() + { + Nombre = "Video de ALex" + }; + Domain.Video result = await handler.Handle(request, CancellationToken.None); + + result.ShouldBeOfType(); + result.Nombre.ShouldBe("Video de ALex"); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/DeleteVideo/DeleteVideoCommandHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/DeleteVideo/DeleteVideoCommandHandlerXUnitTests.cs new file mode 100644 index 0000000..e3ca63b --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/DeleteVideo/DeleteVideoCommandHandlerXUnitTests.cs @@ -0,0 +1,6 @@ +namespace CleanArchitecture.Application.UnitTests.Features.Videos.Commands.DeleteStreamer +{ + public class DeleteVideoCommandHandlerXUnitTests + { + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/UpdateVideo/UpdateVideoCommandHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/UpdateVideo/UpdateVideoCommandHandlerXUnitTests.cs new file mode 100644 index 0000000..8ba8e77 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Commands/UpdateVideo/UpdateVideoCommandHandlerXUnitTests.cs @@ -0,0 +1,61 @@ +using AutoMapper; +using CleanArchitecture.Application.Contracts.Infrastructure; + +using CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer; +using CleanArchitecture.Application.Features.Videos.Commands.UpdateVideo; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Domain; +using CleanArchitecture.Infrastructure.Repositories; +using Microsoft.Extensions.Logging; +using Moq; +using Shouldly; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace CleanArchitecture.Application.UnitTests.Features.Videos.Commands.UpdateStreamer +{ + public class UpdateVideoCommandHandlerXUnitTests + { + private readonly IMapper mapper; + private readonly Mock mockUnitOfWork; + private readonly Mock emailService; + private readonly Mock> logger; + + public UpdateVideoCommandHandlerXUnitTests() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + emailService = new Mock(); + logger = new Mock>(); + + MockVideoRepository.AddDataVideoRepository(mockUnitOfWork.Object.StreamerDbContext); + } + + [Fact] + public async Task UpdateVideoTest() + { + var handler = new UpdateVideoCommandHandler(mockUnitOfWork.Object, mapper, logger.Object); + var request = new UpdateVideoCommand() + { + Id = Guid.Parse("edfe00d5-7599-4788-b52a-acc2a683b188"), + Nombre = "Alex Video 2" + }; + Domain.Video result = await handler.Handle(request, CancellationToken.None); + if(result == null) + { + throw new Exception("Result is null"); + } + result.ShouldBeOfType(); + result.Nombre.ShouldBe("Alex Video 2"); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Queries/GetVideosListQueryHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Queries/GetVideosListQueryHandlerXUnitTests.cs new file mode 100644 index 0000000..e230572 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Queries/GetVideosListQueryHandlerXUnitTests.cs @@ -0,0 +1,41 @@ +using AutoMapper; +using CleanArchitecture.Application.Contracts.Persistence; +using CleanArchitecture.Application.Features.Videos.Queries.GetVideosList; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Infrastructure.Repositories; +using Moq; +using Shouldly; +using Xunit; + +namespace CleanArchitecture.Application.UnitTests.Features.Video.Queries +{ + public class GetVideosListQueryHandlerXUnitTests + { + + private readonly IMapper mapper; + private Mock mockUnitOfWork; + + public GetVideosListQueryHandlerXUnitTests() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + MockVideoRepository.AddDataVideoRepository(mockUnitOfWork.Object.StreamerDbContext); + } + + [Fact] + public async Task GetVideoListTest() + { + var handler = new GetVideosListQueryHandler(mockUnitOfWork.Object, mapper); + var request = new GetVideosListQuery("Alex"); + var result = await handler.Handle(request, CancellationToken.None); + + result.ShouldBeOfType>(); + result.Count.ShouldBe(1); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockStreamerRepository.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockStreamerRepository.cs new file mode 100644 index 0000000..e39c088 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockStreamerRepository.cs @@ -0,0 +1,31 @@ +using AutoFixture; +using CleanArchitecture.Domain; +using CleanArchitecture.Infrastructure.Persistence; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CleanArchitecture.Application.UnitTests.Mocks +{ + public static class MockStreamerRepository + { + public static void AddDataStreamerRepository(StreamerDbContext streamerDbContextFake) + { + var fixture = new Fixture(); + fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + var streamers = fixture.CreateMany().ToList(); + var guidFromText = Guid.Parse("edfe00d5-7599-4788-b52a-acc2a683b188"); + streamers.Add(fixture.Build() + .With(tr => tr.Id, guidFromText) + .Without(tr => tr.Videos) + .Create() + ); + streamerDbContextFake.Streamers!.AddRange(streamers); + streamerDbContextFake.SaveChanges(); + } + + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockUnitOfWork.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockUnitOfWork.cs new file mode 100644 index 0000000..aa57ee6 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockUnitOfWork.cs @@ -0,0 +1,29 @@ + +using CleanArchitecture.Infrastructure.Persistence; +using CleanArchitecture.Infrastructure.Repositories; +using Microsoft.EntityFrameworkCore; +using Moq; + +namespace CleanArchitecture.Application.UnitTests.Mocks +{ + + public static class MockUnitOfWork + { + public static Mock GetUnitOfWork() + { + DbContextOptions options; +//#if DEBUG + +//#else + options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: $"StreamerDbContext-{Guid.NewGuid()}").Options; +//#endif + var stramerDbContextFake = new StreamerDbContext(options); + + stramerDbContextFake.Database.EnsureDeleted(); + var mockUnitOfWork = new Mock(stramerDbContextFake); + + return mockUnitOfWork; + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockVideoRepository.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockVideoRepository.cs new file mode 100644 index 0000000..4a03542 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockVideoRepository.cs @@ -0,0 +1,31 @@ +using AutoFixture; +using CleanArchitecture.Application.Contracts.Persistence; +using CleanArchitecture.Domain; +using CleanArchitecture.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Moq; +using CleanArchitecture.Infrastructure.Repositories; + +namespace CleanArchitecture.Application.UnitTests.Mocks +{ + public static class MockVideoRepository + { + public static void AddDataVideoRepository(StreamerDbContext streamerDbContextFake) + { + var fixture = new Fixture(); + fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + var videos = fixture.CreateMany + + + - diff --git a/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IAsyncRepository.cs b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IAsyncRepository.cs index 0dc3232..8b81289 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IAsyncRepository.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IAsyncRepository.cs @@ -15,11 +15,15 @@ namespace CleanArchitecture.Application.Contracts.Persistence Func, IOrderedQueryable>? orderBy = null, List>>? includes = null, bool disableTracking = true); - Task GetByIdAsync(int id); + Task GetByIdAsync(Guid id); Task AddAsync(T entity); Task UpdateAsync(T entity); Task DeleteAsync(T entity); + void AddEntity(T entity); + void UpdateEntity(T entity); + void DeleteEntity(T entity); + } } diff --git a/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IUnitOfWork.cs b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IUnitOfWork.cs new file mode 100644 index 0000000..1c5bacb --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IUnitOfWork.cs @@ -0,0 +1,14 @@ +using CleanArchitecture.Domain.Common; + +namespace CleanArchitecture.Application.Contracts.Persistence +{ + public interface IUnitOfWork: IDisposable + { + + IStreamerRepository StreamerRepository { get; } + IVideoRepository VideoRepository { get; } + IAsyncRepository Repository() where T : BaseDomainModel; + + Task Complete(); + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommand.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommand.cs new file mode 100644 index 0000000..99e91ce --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommand.cs @@ -0,0 +1,11 @@ +using MediatR; + +namespace CleanArchitecture.Application.Features.Directors.Commands.CreateDirector +{ + public class CreateDirectorCommand: IRequest + { + public string Nombre { get; set; } = string.Empty; + public string Apellido { get; set; } = string.Empty; + public int VideoId { get; set; } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommandHandler.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommandHandler.cs new file mode 100644 index 0000000..6bf48f8 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommandHandler.cs @@ -0,0 +1,41 @@ +using AutoMapper; +using CleanArchitecture.Application.Contracts.Persistence; +using CleanArchitecture.Domain; +using MediatR; +using Microsoft.Extensions.Logging; + +namespace CleanArchitecture.Application.Features.Directors.Commands.CreateDirector +{ + public class CreateDirectorCommandHandler : IRequestHandler + { + private readonly ILogger logger; + private readonly IMapper mapper; + private readonly IUnitOfWork unitOfWork; + + public CreateDirectorCommandHandler(ILogger logger, IMapper mapper, IUnitOfWork unitOfWork) + { + this.logger = logger; + this.mapper = mapper; + this.unitOfWork = unitOfWork; + } + + public Task Handle(CreateDirectorCommand request, CancellationToken cancellationToken) + { + var directorEntity = mapper.Map(request); + unitOfWork.Repository().AddEntity(directorEntity); + var response = unitOfWork.Complete(); + + if (response.Result > 0) + { + logger.LogInformation($"Director {directorEntity.Id} is successfully created."); + return Task.FromResult(directorEntity.Id); + } + else + { + logger.LogError($"Director {directorEntity.Id} creation failed."); + throw new Exception("Director creation failed."); + } + + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommandValidator.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommandValidator.cs new file mode 100644 index 0000000..68a3175 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Directors/Commands/CreateDirector/CreateDirectorCommandValidator.cs @@ -0,0 +1,21 @@ +using CleanArchitecture.Application.Features.Streamers.Commands.CreateStreamer; +using FluentValidation; + +namespace CleanArchitecture.Application.Features.Directors.Commands.CreateDirector +{ + public class CreateDirectorCommandValidator : AbstractValidator + { + + public CreateDirectorCommandValidator() + { + RuleFor(p=>p.Nombre).NotEmpty().WithMessage("{Nombre} is required.") + .NotNull() + .MaximumLength(50).WithMessage("{Nombre} must not exceed 50 characters."); + + RuleFor(p => p.Apellido) + .NotEmpty().WithMessage("{Apellido} is required.") + .NotNull() + .MaximumLength(100).WithMessage("{Apellido} must not exceed 50 characters."); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommand.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommand.cs index 6651d01..1b9e475 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommand.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommand.cs @@ -1,8 +1,9 @@ -using MediatR; +using CleanArchitecture.Domain; +using MediatR; namespace CleanArchitecture.Application.Features.Streamers.Commands.CreateStreamer { - public class CreateStreamerCommand : IRequest + public class CreateStreamerCommand : IRequest { public string Nombre { get; set; } = string.Empty; public string Url { get; set; } = string.Empty; diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommandHandler.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommandHandler.cs index 2abdbc1..981f4b5 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommandHandler.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/CreateStreamer/CreateStreamerCommandHandler.cs @@ -8,22 +8,31 @@ using Microsoft.Extensions.Logging; namespace CleanArchitecture.Application.Features.Streamers.Commands.CreateStreamer { - public class CreateStreamerCommandHandler(IStreamerRepository _streamerRepository, IMapper _mapper, + public class CreateStreamerCommandHandler(IUnitOfWork _unitOfWork, IMapper _mapper, IEmailService _emailService, ILogger _logger) : - IRequestHandler + IRequestHandler { - private readonly IStreamerRepository streamerRepository = _streamerRepository; + private readonly IUnitOfWork unitOfWork = _unitOfWork; private readonly IMapper mapper = _mapper; private readonly IEmailService emailService = _emailService; private readonly ILogger logger = _logger; - public async Task Handle(CreateStreamerCommand request, CancellationToken cancellationToken) + public async Task Handle(CreateStreamerCommand request, CancellationToken cancellationToken) { var streamerEntity = mapper.Map(request); - var newStreamer = await streamerRepository.AddAsync(streamerEntity); - logger.LogInformation($"Streamer {newStreamer.Id} is successfully created."); - await SendEmail(newStreamer); - return newStreamer.Id; + unitOfWork.StreamerRepository.AddEntity(streamerEntity); + var response = await unitOfWork.Complete(); + if(response > 0) + { + logger.LogInformation($"Streamer {streamerEntity.Id} is successfully created."); + await SendEmail(streamerEntity); + return streamerEntity; + } + else + { + throw new Exception("Failed to create the streamer."); + } + } private async Task SendEmail(Streamer streamer) diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommand.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommand.cs index 15956f7..34cd7f4 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommand.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommand.cs @@ -4,6 +4,6 @@ namespace CleanArchitecture.Application.Features.Streamers.Commands.DeleteStream { public class DeleteStreamerCommand: IRequest { - public int Id { get; set; } + public Guid Id { get; set; } } } diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandler.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandler.cs index 40f3cb2..c4e954d 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandler.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandler.cs @@ -9,27 +9,28 @@ namespace CleanArchitecture.Application.Features.Streamers.Commands.DeleteStream { public class DeleteStreamerCommandHandler : IRequestHandler { - private readonly IStreamerRepository streamerRepository; + private readonly IUnitOfWork unitOfWork; private readonly IMapper mapper; private readonly ILogger logger; - public DeleteStreamerCommandHandler(IStreamerRepository streamerRepository, IMapper mapper, ILogger logger) + public DeleteStreamerCommandHandler(IUnitOfWork unitOfWork, IMapper mapper, ILogger logger) { - this.streamerRepository = streamerRepository; + this.unitOfWork = unitOfWork; this.mapper = mapper; this.logger = logger; } public async Task Handle(DeleteStreamerCommand request, CancellationToken cancellationToken) { - var streamerToDelete = await streamerRepository.GetByIdAsync(request.Id); + var streamerToDelete = await unitOfWork.StreamerRepository.GetByIdAsync(request.Id); if (streamerToDelete == null) { logger.LogError($"Streamer with id {request.Id} not found."); throw new NotFoundException(nameof(Streamer), request.Id); } - await streamerRepository.DeleteAsync(streamerToDelete); + unitOfWork.StreamerRepository.DeleteEntity(streamerToDelete); + await unitOfWork.Complete(); logger.LogInformation($"Streamer {streamerToDelete.Id} is successfully deleted."); return Unit.Value; diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommand.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommand.cs index 896856a..44d505e 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommand.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommand.cs @@ -1,10 +1,11 @@ -using MediatR; +using CleanArchitecture.Domain; +using MediatR; namespace CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer { - public class UpdateStreamerCommand : IRequest + public class UpdateStreamerCommand : IRequest { - public int Id { get; set; } + public Guid Id { get; set; } public string Nombre { get; set; } = string.Empty; public string Url { get; set; } = string.Empty; } diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommandHandler.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommandHandler.cs index 5254f93..48c3b25 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommandHandler.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Streamers/Commands/UpdateStreamer/UpdateStreamerCommandHandler.cs @@ -7,23 +7,23 @@ using Microsoft.Extensions.Logging; namespace CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer { - public class UpdateStreamerCommandHandler : IRequestHandler + public class UpdateStreamerCommandHandler : IRequestHandler { - private readonly IStreamerRepository streamerRepository; + private readonly IUnitOfWork unitOfWork; private readonly IMapper mapper; private readonly ILogger logger; - public UpdateStreamerCommandHandler(IStreamerRepository streamerRepository, + public UpdateStreamerCommandHandler(IUnitOfWork unitOfWork, IMapper mapper, ILogger logger) { - this.streamerRepository = streamerRepository; + this.unitOfWork = unitOfWork; this.mapper = mapper; this.logger = logger; } - public async Task Handle(UpdateStreamerCommand request, CancellationToken cancellationToken) + public async Task Handle(UpdateStreamerCommand request, CancellationToken cancellationToken) { - var streamerToUpdate = await streamerRepository.GetByIdAsync(request.Id); + var streamerToUpdate = await unitOfWork.StreamerRepository.GetByIdAsync(request.Id); if(streamerToUpdate == null) { logger.LogError($"Streamer with id {request.Id} not found."); @@ -32,11 +32,17 @@ namespace CleanArchitecture.Application.Features.Streamers.Commands.UpdateStream mapper.Map(request, streamerToUpdate, typeof(UpdateStreamerCommand), typeof(Streamer)); - await streamerRepository.UpdateAsync(streamerToUpdate); + unitOfWork.StreamerRepository.UpdateEntity(streamerToUpdate); + var result = await unitOfWork.Complete(); + if(result == 0) + { + logger.LogError($"{Guid.NewGuid()} - Update of streamer {request.Id} failed."); + throw new Exception($"Update of streamer {request.Id} failed."); + } logger.LogInformation($"Streamer {streamerToUpdate.Id} is successfully updated."); - return Unit.Value; + return streamerToUpdate; } } } diff --git a/CleanArchitecture/CleanArchitecture.Application/Features/Videos/Commands/CreateVideo/CreateVideoCommand.cs b/CleanArchitecture/CleanArchitecture.Application/Features/Videos/Commands/CreateVideo/CreateVideoCommand.cs new file mode 100644 index 0000000..985e283 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application/Features/Videos/Commands/CreateVideo/CreateVideoCommand.cs @@ -0,0 +1,11 @@ +using CleanArchitecture.Domain; +using MediatR; + +namespace CleanArchitecture.Application.Features.Videos.Commands.CreateVideo +{ + public class CreateVideoCommand : IRequest + + + + diff --git a/CleanArchitecture/CleanArchitecture.Data/InfrastructureServiceRegistration.cs b/CleanArchitecture/CleanArchitecture.Data/InfrastructureServiceRegistration.cs index afa138f..8ca81ae 100644 --- a/CleanArchitecture/CleanArchitecture.Data/InfrastructureServiceRegistration.cs +++ b/CleanArchitecture/CleanArchitecture.Data/InfrastructureServiceRegistration.cs @@ -22,6 +22,8 @@ namespace CleanArchitecture.Infrastructure .LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name }, Microsoft.Extensions.Logging.LogLevel.Information) ); + services.AddScoped(); + services.AddScoped(typeof(IAsyncRepository<>), typeof(RepositoryBase<>)); services.AddScoped(); services.AddScoped(); diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215190923_Second-Migration.Designer.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215190923_Second-Migration.Designer.cs deleted file mode 100644 index 7441255..0000000 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215190923_Second-Migration.Designer.cs +++ /dev/null @@ -1,163 +0,0 @@ -// -using System; -using CleanArchitecture.Infrastructure.Persistence; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CleanArchitecture.Data.Migrations -{ - [DbContext(typeof(StreamerDbContext))] - [Migration("20240215190923_Second-Migration")] - partial class SecondMigration - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.2") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("CleanArchitecture.Domain.Actor", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Actor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("VideoId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("Director"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("Url") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Streamers"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("DirectorId") - .HasColumnType("int"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("StreamerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("DirectorId") - .IsUnique(); - - b.HasIndex("StreamerId"); - - b.ToTable("Videos"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.Property("VideoId") - .HasColumnType("int"); - - b.Property("ActorId") - .HasColumnType("int"); - - b.HasKey("VideoId", "ActorId"); - - b.HasIndex("ActorId"); - - b.ToTable("VideoActor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.HasOne("CleanArchitecture.Domain.Director", "Director") - .WithOne("Video") - .HasForeignKey("CleanArchitecture.Domain.Video", "DirectorId"); - - b.HasOne("CleanArchitecture.Domain.Streamer", "Streamer") - .WithMany("Videos") - .HasForeignKey("StreamerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Director"); - - b.Navigation("Streamer"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.HasOne("CleanArchitecture.Domain.Actor", null) - .WithMany() - .HasForeignKey("ActorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("CleanArchitecture.Domain.Video", null) - .WithMany() - .HasForeignKey("VideoId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Navigation("Video"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Navigation("Videos"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215190923_Second-Migration.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215190923_Second-Migration.cs deleted file mode 100644 index 25fa33f..0000000 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215190923_Second-Migration.cs +++ /dev/null @@ -1,148 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace CleanArchitecture.Data.Migrations -{ - /// - public partial class SecondMigration : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Videos_Streamers_StreamerId", - table: "Videos"); - - migrationBuilder.AddColumn( - name: "DirectorId", - table: "Videos", - type: "int", - nullable: true); - - migrationBuilder.CreateTable( - name: "Actor", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Nombre = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Apellido = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Actor", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Director", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Nombre = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Apellido = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - VideoId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Director", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "VideoActor", - columns: table => new - { - VideoId = table.Column(type: "int", nullable: false), - ActorId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_VideoActor", x => new { x.VideoId, x.ActorId }); - table.ForeignKey( - name: "FK_VideoActor_Actor_ActorId", - column: x => x.ActorId, - principalTable: "Actor", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_VideoActor_Videos_VideoId", - column: x => x.VideoId, - principalTable: "Videos", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_Videos_DirectorId", - table: "Videos", - column: "DirectorId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_VideoActor_ActorId", - table: "VideoActor", - column: "ActorId"); - - migrationBuilder.AddForeignKey( - name: "FK_Videos_Director_DirectorId", - table: "Videos", - column: "DirectorId", - principalTable: "Director", - principalColumn: "Id"); - - migrationBuilder.AddForeignKey( - name: "FK_Videos_Streamers_StreamerId", - table: "Videos", - column: "StreamerId", - principalTable: "Streamers", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Videos_Director_DirectorId", - table: "Videos"); - - migrationBuilder.DropForeignKey( - name: "FK_Videos_Streamers_StreamerId", - table: "Videos"); - - migrationBuilder.DropTable( - name: "Director"); - - migrationBuilder.DropTable( - name: "VideoActor"); - - migrationBuilder.DropTable( - name: "Actor"); - - migrationBuilder.DropIndex( - name: "IX_Videos_DirectorId", - table: "Videos"); - - migrationBuilder.DropColumn( - name: "DirectorId", - table: "Videos"); - - migrationBuilder.AddForeignKey( - name: "FK_Videos_Streamers_StreamerId", - table: "Videos", - column: "StreamerId", - principalTable: "Streamers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - } -} diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215201317_BaseDomainModelUpdate.Designer.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215201317_BaseDomainModelUpdate.Designer.cs deleted file mode 100644 index 3cfd79b..0000000 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215201317_BaseDomainModelUpdate.Designer.cs +++ /dev/null @@ -1,215 +0,0 @@ -// -using System; -using CleanArchitecture.Infrastructure.Persistence; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CleanArchitecture.Data.Migrations -{ - [DbContext(typeof(StreamerDbContext))] - [Migration("20240215201317_BaseDomainModelUpdate")] - partial class BaseDomainModelUpdate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.2") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("CleanArchitecture.Domain.Actor", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Actor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("VideoId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("Director"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("Url") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Streamers"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("DirectorId") - .HasColumnType("int"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("StreamerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("DirectorId") - .IsUnique(); - - b.HasIndex("StreamerId"); - - b.ToTable("Videos"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.Property("VideoId") - .HasColumnType("int"); - - b.Property("ActorId") - .HasColumnType("int"); - - b.HasKey("VideoId", "ActorId"); - - b.HasIndex("ActorId"); - - b.ToTable("VideoActor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.HasOne("CleanArchitecture.Domain.Director", "Director") - .WithOne("Video") - .HasForeignKey("CleanArchitecture.Domain.Video", "DirectorId"); - - b.HasOne("CleanArchitecture.Domain.Streamer", "Streamer") - .WithMany("Videos") - .HasForeignKey("StreamerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Director"); - - b.Navigation("Streamer"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.HasOne("CleanArchitecture.Domain.Actor", "Actor") - .WithMany() - .HasForeignKey("ActorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("CleanArchitecture.Domain.Video", "Video") - .WithMany() - .HasForeignKey("VideoId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Actor"); - - b.Navigation("Video"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Navigation("Video"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Navigation("Videos"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215201317_BaseDomainModelUpdate.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215201317_BaseDomainModelUpdate.cs deleted file mode 100644 index 566e248..0000000 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215201317_BaseDomainModelUpdate.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace CleanArchitecture.Data.Migrations -{ - /// - public partial class BaseDomainModelUpdate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CreatedBy", - table: "Videos", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "CreatedDate", - table: "Videos", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "LastModifiedBy", - table: "Videos", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "LastModifiedDate", - table: "Videos", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "CreatedBy", - table: "Streamers", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "CreatedDate", - table: "Streamers", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "LastModifiedBy", - table: "Streamers", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "LastModifiedDate", - table: "Streamers", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "CreatedBy", - table: "Director", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "CreatedDate", - table: "Director", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "LastModifiedBy", - table: "Director", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "LastModifiedDate", - table: "Director", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "CreatedBy", - table: "Actor", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "CreatedDate", - table: "Actor", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "LastModifiedBy", - table: "Actor", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "LastModifiedDate", - table: "Actor", - type: "datetime(6)", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CreatedBy", - table: "Videos"); - - migrationBuilder.DropColumn( - name: "CreatedDate", - table: "Videos"); - - migrationBuilder.DropColumn( - name: "LastModifiedBy", - table: "Videos"); - - migrationBuilder.DropColumn( - name: "LastModifiedDate", - table: "Videos"); - - migrationBuilder.DropColumn( - name: "CreatedBy", - table: "Streamers"); - - migrationBuilder.DropColumn( - name: "CreatedDate", - table: "Streamers"); - - migrationBuilder.DropColumn( - name: "LastModifiedBy", - table: "Streamers"); - - migrationBuilder.DropColumn( - name: "LastModifiedDate", - table: "Streamers"); - - migrationBuilder.DropColumn( - name: "CreatedBy", - table: "Director"); - - migrationBuilder.DropColumn( - name: "CreatedDate", - table: "Director"); - - migrationBuilder.DropColumn( - name: "LastModifiedBy", - table: "Director"); - - migrationBuilder.DropColumn( - name: "LastModifiedDate", - table: "Director"); - - migrationBuilder.DropColumn( - name: "CreatedBy", - table: "Actor"); - - migrationBuilder.DropColumn( - name: "CreatedDate", - table: "Actor"); - - migrationBuilder.DropColumn( - name: "LastModifiedBy", - table: "Actor"); - - migrationBuilder.DropColumn( - name: "LastModifiedDate", - table: "Actor"); - } - } -} diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240218123327_cleanArchitectureFromApi.Designer.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240218123327_cleanArchitectureFromApi.Designer.cs deleted file mode 100644 index 8757082..0000000 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240218123327_cleanArchitectureFromApi.Designer.cs +++ /dev/null @@ -1,230 +0,0 @@ -// -using System; -using CleanArchitecture.Infrastructure.Persistence; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CleanArchitecture.Data.Migrations -{ - [DbContext(typeof(StreamerDbContext))] - [Migration("20240218123327_cleanArchitectureFromApi")] - partial class cleanArchitectureFromApi - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.2") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("CleanArchitecture.Domain.Actor", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Actor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("VideoId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("Director"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("Url") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Streamers"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("DirectorId") - .HasColumnType("int"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("StreamerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("DirectorId") - .IsUnique(); - - b.HasIndex("StreamerId"); - - b.ToTable("Videos"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.Property("VideoId") - .HasColumnType("int"); - - b.Property("ActorId") - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("Id") - .HasColumnType("int"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.HasKey("VideoId", "ActorId"); - - b.HasIndex("ActorId"); - - b.ToTable("VideoActor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.HasOne("CleanArchitecture.Domain.Director", "Director") - .WithOne("Video") - .HasForeignKey("CleanArchitecture.Domain.Video", "DirectorId"); - - b.HasOne("CleanArchitecture.Domain.Streamer", "Streamer") - .WithMany("Videos") - .HasForeignKey("StreamerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Director"); - - b.Navigation("Streamer"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.HasOne("CleanArchitecture.Domain.Actor", "Actor") - .WithMany() - .HasForeignKey("ActorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("CleanArchitecture.Domain.Video", "Video") - .WithMany() - .HasForeignKey("VideoId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Actor"); - - b.Navigation("Video"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Navigation("Video"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Navigation("Videos"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240218123327_cleanArchitectureFromApi.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240218123327_cleanArchitectureFromApi.cs deleted file mode 100644 index 6ff4d37..0000000 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240218123327_cleanArchitectureFromApi.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace CleanArchitecture.Data.Migrations -{ - /// - public partial class cleanArchitectureFromApi : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CreatedBy", - table: "VideoActor", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "CreatedDate", - table: "VideoActor", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "Id", - table: "VideoActor", - type: "int", - nullable: false, - defaultValue: 0); - - migrationBuilder.AddColumn( - name: "LastModifiedBy", - table: "VideoActor", - type: "longtext", - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "LastModifiedDate", - table: "VideoActor", - type: "datetime(6)", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CreatedBy", - table: "VideoActor"); - - migrationBuilder.DropColumn( - name: "CreatedDate", - table: "VideoActor"); - - migrationBuilder.DropColumn( - name: "Id", - table: "VideoActor"); - - migrationBuilder.DropColumn( - name: "LastModifiedBy", - table: "VideoActor"); - - migrationBuilder.DropColumn( - name: "LastModifiedDate", - table: "VideoActor"); - } - } -} diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215100525_InitialMigration.Designer.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240221215002_Initial-Migration.Designer.cs similarity index 51% rename from CleanArchitecture/CleanArchitecture.Data/Migrations/20240215100525_InitialMigration.Designer.cs rename to CleanArchitecture/CleanArchitecture.Data/Migrations/20240221215002_Initial-Migration.Designer.cs index 7fcaa6c..d7045fc 100644 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215100525_InitialMigration.Designer.cs +++ b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240221215002_Initial-Migration.Designer.cs @@ -1,4 +1,5 @@ // +using System; using CleanArchitecture.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -7,10 +8,10 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; #nullable disable -namespace CleanArchitecture.Data.Migrations +namespace CleanArchitecture.Infrastructure.Migrations { [DbContext(typeof(StreamerDbContext))] - [Migration("20240215100525_InitialMigration")] + [Migration("20240221215002_Initial-Migration")] partial class InitialMigration { /// @@ -23,9 +24,22 @@ namespace CleanArchitecture.Data.Migrations modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("binary(16)") + .HasColumnName("Id"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("LastModifiedBy") + .HasColumnType("longtext"); + + b.Property("LastModifiedDate") + .HasColumnType("datetime(6)"); b.Property("Nombre") .HasColumnType("longtext"); @@ -40,15 +54,29 @@ namespace CleanArchitecture.Data.Migrations modelBuilder.Entity("CleanArchitecture.Domain.Video", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("binary(16)") + .HasColumnName("Id"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("LastModifiedBy") + .HasColumnType("longtext"); + + b.Property("LastModifiedDate") + .HasColumnType("datetime(6)"); b.Property("Nombre") .HasColumnType("longtext"); - b.Property("StreamerId") - .HasColumnType("int"); + b.Property("StreamerId") + .IsRequired() + .HasColumnType("binary(16)"); b.HasKey("Id"); @@ -60,13 +88,18 @@ namespace CleanArchitecture.Data.Migrations modelBuilder.Entity("CleanArchitecture.Domain.Video", b => { b.HasOne("CleanArchitecture.Domain.Streamer", "Streamer") - .WithMany() + .WithMany("Videos") .HasForeignKey("StreamerId") - .OnDelete(DeleteBehavior.Cascade) + .OnDelete(DeleteBehavior.NoAction) .IsRequired(); b.Navigation("Streamer"); }); + + modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => + { + b.Navigation("Videos"); + }); #pragma warning restore 612, 618 } } diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215100525_InitialMigration.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240221215002_Initial-Migration.cs similarity index 59% rename from CleanArchitecture/CleanArchitecture.Data/Migrations/20240215100525_InitialMigration.cs rename to CleanArchitecture/CleanArchitecture.Data/Migrations/20240221215002_Initial-Migration.cs index b21c5f0..6c81729 100644 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/20240215100525_InitialMigration.cs +++ b/CleanArchitecture/CleanArchitecture.Data/Migrations/20240221215002_Initial-Migration.cs @@ -1,9 +1,9 @@ -using Microsoft.EntityFrameworkCore.Metadata; +using System; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace CleanArchitecture.Data.Migrations +namespace CleanArchitecture.Infrastructure.Migrations { /// public partial class InitialMigration : Migration @@ -18,11 +18,16 @@ namespace CleanArchitecture.Data.Migrations name: "Streamers", columns: table => new { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Id = table.Column(type: "binary(16)", nullable: false), Nombre = table.Column(type: "longtext", nullable: true) .Annotation("MySql:CharSet", "utf8mb4"), Url = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedDate = table.Column(type: "datetime(6)", nullable: true), + CreatedBy = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + LastModifiedDate = table.Column(type: "datetime(6)", nullable: true), + LastModifiedBy = table.Column(type: "longtext", nullable: true) .Annotation("MySql:CharSet", "utf8mb4") }, constraints: table => @@ -35,11 +40,16 @@ namespace CleanArchitecture.Data.Migrations name: "Videos", columns: table => new { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Id = table.Column(type: "binary(16)", nullable: false), Nombre = table.Column(type: "longtext", nullable: true) .Annotation("MySql:CharSet", "utf8mb4"), - StreamerId = table.Column(type: "int", nullable: false) + StreamerId = table.Column(type: "binary(16)", nullable: false), + CreatedDate = table.Column(type: "datetime(6)", nullable: true), + CreatedBy = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + LastModifiedDate = table.Column(type: "datetime(6)", nullable: true), + LastModifiedBy = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") }, constraints: table => { @@ -48,8 +58,7 @@ namespace CleanArchitecture.Data.Migrations name: "FK_Videos_Streamers_StreamerId", column: x => x.StreamerId, principalTable: "Streamers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); + principalColumn: "Id"); }) .Annotation("MySql:CharSet", "utf8mb4"); diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/ApplicationDbContextModelSnapshot.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index 9a1baf8..0000000 --- a/CleanArchitecture/CleanArchitecture.Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,227 +0,0 @@ -// -using System; -using CleanArchitecture.Infrastructure.Persistence; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CleanArchitecture.Data.Migrations -{ - [DbContext(typeof(StreamerDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.2") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("CleanArchitecture.Domain.Actor", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Actor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Apellido") - .HasColumnType("longtext"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("VideoId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("Director"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("Url") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Streamers"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("DirectorId") - .HasColumnType("int"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.Property("Nombre") - .HasColumnType("longtext"); - - b.Property("StreamerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("DirectorId") - .IsUnique(); - - b.HasIndex("StreamerId"); - - b.ToTable("Videos"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.Property("VideoId") - .HasColumnType("int"); - - b.Property("ActorId") - .HasColumnType("int"); - - b.Property("CreatedBy") - .HasColumnType("longtext"); - - b.Property("CreatedDate") - .HasColumnType("datetime(6)"); - - b.Property("Id") - .HasColumnType("int"); - - b.Property("LastModifiedBy") - .HasColumnType("longtext"); - - b.Property("LastModifiedDate") - .HasColumnType("datetime(6)"); - - b.HasKey("VideoId", "ActorId"); - - b.HasIndex("ActorId"); - - b.ToTable("VideoActor"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Video", b => - { - b.HasOne("CleanArchitecture.Domain.Director", "Director") - .WithOne("Video") - .HasForeignKey("CleanArchitecture.Domain.Video", "DirectorId"); - - b.HasOne("CleanArchitecture.Domain.Streamer", "Streamer") - .WithMany("Videos") - .HasForeignKey("StreamerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Director"); - - b.Navigation("Streamer"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.VideoActor", b => - { - b.HasOne("CleanArchitecture.Domain.Actor", "Actor") - .WithMany() - .HasForeignKey("ActorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("CleanArchitecture.Domain.Video", "Video") - .WithMany() - .HasForeignKey("VideoId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Actor"); - - b.Navigation("Video"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Director", b => - { - b.Navigation("Video"); - }); - - modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => - { - b.Navigation("Videos"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/CleanArchitecture/CleanArchitecture.Data/Migrations/StreamerDbContextModelSnapshot.cs b/CleanArchitecture/CleanArchitecture.Data/Migrations/StreamerDbContextModelSnapshot.cs new file mode 100644 index 0000000..3ddc6be --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Data/Migrations/StreamerDbContextModelSnapshot.cs @@ -0,0 +1,103 @@ +// +using System; +using CleanArchitecture.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CleanArchitecture.Infrastructure.Migrations +{ + [DbContext(typeof(StreamerDbContext))] + partial class StreamerDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)") + .HasColumnName("Id"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("LastModifiedBy") + .HasColumnType("longtext"); + + b.Property("LastModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Nombre") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Streamers"); + }); + + modelBuilder.Entity("CleanArchitecture.Domain.Video", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("binary(16)") + .HasColumnName("Id"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("LastModifiedBy") + .HasColumnType("longtext"); + + b.Property("LastModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Nombre") + .HasColumnType("longtext"); + + b.Property("StreamerId") + .IsRequired() + .HasColumnType("binary(16)"); + + b.HasKey("Id"); + + b.HasIndex("StreamerId"); + + b.ToTable("Videos"); + }); + + modelBuilder.Entity("CleanArchitecture.Domain.Video", b => + { + b.HasOne("CleanArchitecture.Domain.Streamer", "Streamer") + .WithMany("Videos") + .HasForeignKey("StreamerId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Streamer"); + }); + + modelBuilder.Entity("CleanArchitecture.Domain.Streamer", b => + { + b.Navigation("Videos"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Data/Persistence/StreamerDbContext.cs b/CleanArchitecture/CleanArchitecture.Data/Persistence/StreamerDbContext.cs index 631d7d5..5d3ce1d 100644 --- a/CleanArchitecture/CleanArchitecture.Data/Persistence/StreamerDbContext.cs +++ b/CleanArchitecture/CleanArchitecture.Data/Persistence/StreamerDbContext.cs @@ -10,10 +10,16 @@ using System.Threading.Tasks; namespace CleanArchitecture.Infrastructure.Persistence { + + /// + /// Add-Migration Migration-Name -Context StreamerDbContext + /// Remove-Migration -Context StreamerDbContext + /// Update-Database -Context StreamerDbContext + /// public class StreamerDbContext : DbContext { - public StreamerDbContext(DbContextOptions options) : base(options) - { + public StreamerDbContext(DbContextOptions options) : base(options) + { } //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) @@ -26,13 +32,13 @@ namespace CleanArchitecture.Infrastructure.Persistence public override Task SaveChangesAsync(CancellationToken cancellationToken = default) { - foreach(var entry in ChangeTracker.Entries()) + foreach (var entry in ChangeTracker.Entries()) { switch (entry.State) { case EntityState.Modified: entry.Entity.LastModifiedBy = "System"; - entry.Entity.LastModifiedDate = DateTime.Now; + entry.Entity.LastModifiedDate = DateTime.Now; break; case EntityState.Added: entry.Entity.CreatedDate = DateTime.Now; @@ -43,7 +49,7 @@ namespace CleanArchitecture.Infrastructure.Persistence case EntityState.Unchanged: break; case EntityState.Deleted: - break; + break; default: break; } @@ -53,37 +59,70 @@ namespace CleanArchitecture.Infrastructure.Persistence protected override void OnModelCreating(ModelBuilder mb) { - mb.Entity() - .HasMany(x => x.Videos) + + mb.Entity(entity => + { + entity.Property(e => e.Id) + .HasColumnName("Id") + .HasColumnType("binary(16)") // Especifica el tipo de columna y tamaño correcto + .HasConversion( + id => id.ToByteArray(), // Convierte de Guid a byte[] al guardar + bytes => new Guid(bytes) // Convierte de byte[] a Guid al leer + ); + entity.HasMany(x => x.Videos) .WithOne(x => x.Streamer) .HasForeignKey(x => x.StreamerId) .IsRequired() .OnDelete(DeleteBehavior.Restrict); + }); - mb.Entity