بلاخره تموم شد
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
using System.Data;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Application.Data;
|
||||
|
||||
public interface ISqlConnectionFactory
|
||||
{
|
||||
IDbConnection GetOpenConnection();
|
||||
|
||||
IDbConnection CreateNewConnection();
|
||||
|
||||
string GetConnectionString();
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using VizhTalk.BuildingBlocks.Domain;
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Infrastructure;
|
||||
namespace VizhTalk.BuildingBlocks.Application;
|
||||
|
||||
public interface IExecutor
|
||||
{
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace VizhTalk.BuildingBlocks.Application;
|
||||
|
||||
public interface IUnitOfWorkBase : IDisposable
|
||||
{
|
||||
Task<int> CommitAsync(
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -7,11 +7,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VizhTalk.BuildingBlocks.Domain\VizhTalk.BuildingBlocks.Domain.csproj" />
|
||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\" />
|
||||
<ProjectReference Include="..\VizhTalk.BuildingBlocks.Domain\VizhTalk.BuildingBlocks.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
|
||||
public abstract record CommandBase<T> : ICommand<T>
|
||||
{
|
||||
public Guid Id { get; private set; }
|
||||
protected CommandBase()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
}
|
||||
protected CommandBase(Guid id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract record CommandBase : ICommand
|
||||
{
|
||||
public Guid Id { get; private set; }
|
||||
protected CommandBase()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
}
|
||||
protected CommandBase(Guid id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
public interface ICommand<out TResult>
|
||||
{
|
||||
Guid Id { get; }
|
||||
}
|
||||
|
||||
public interface ICommand
|
||||
{
|
||||
Guid Id { get; }
|
||||
}
|
||||
|
||||
@@ -37,4 +37,9 @@ public abstract class Entity<T>
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDeleted(bool val)
|
||||
=> IsDeleted = val;
|
||||
|
||||
public void SetActive(bool val)
|
||||
=> IsActive = val;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Domain.Exceptions.GuardExceptions
|
||||
{
|
||||
public class MaxLengthException(string name, int length)
|
||||
: Exception($"The {name} field cannot be longer than {length} characters."), IGuardException
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,6 @@ using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Domain.Exceptions.GuardExceptions;
|
||||
|
||||
public class NullOrEmptyException(string message) : Exception(message), IGuardException
|
||||
public class NullOrEmptyException(string name) : Exception($"{name} cannot be empty"), IGuardException
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,5 +4,8 @@
|
||||
{
|
||||
public static void NullOrEmpty(this string value, string name)
|
||||
=> StringGuard.NullOrEmpty(value, name);
|
||||
|
||||
public static void MaxLength(this string value, string name, int length)
|
||||
=> StringGuard.MaxLength(value, length, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,15 @@ namespace VizhTalk.BuildingBlocks.Domain.Guards;
|
||||
|
||||
internal static class StringGuard
|
||||
{
|
||||
internal static void NullOrEmpty(string value,string name)
|
||||
internal static void NullOrEmpty(string value, string name)
|
||||
{
|
||||
if(string.IsNullOrEmpty(value))
|
||||
throw new NullOrEmptyException($"{name} cannot be empty");
|
||||
if (string.IsNullOrEmpty(value))
|
||||
throw new NullOrEmptyException(name);
|
||||
}
|
||||
internal static void MaxLength(string value, int length, string name)
|
||||
{
|
||||
if (value.Length > length)
|
||||
throw new MaxLengthException(name, length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
namespace VizhTalk.BuildingBlocks.Domain;
|
||||
|
||||
public interface IRepositoryBase<TDomain, TId>
|
||||
where TDomain : Entity<TId> where TId : ITypeIdValueBase
|
||||
public interface IRepositoryBase<T,TId>
|
||||
where T : Entity<TId> where TId : ITypeIdValueBase
|
||||
{
|
||||
Task<TDomain> CreateAsync(TDomain entity, CancellationToken cancellationToken = default);
|
||||
Task<TDomain> UpdateAsync(TDomain entity, CancellationToken cancellationToken = default);
|
||||
Task DeleteAsync(TId id, CancellationToken cancellationToken = default);
|
||||
Task<TDomain> GetByIdAsync(TId id, CancellationToken cancellationToken = default);
|
||||
Task<T> AddAsync(T entity,CancellationToken cancellationToken = default);
|
||||
Task UpdateAsync(T entity,CancellationToken cancellationToken = default);
|
||||
Task DeleteAsync(T entity,CancellationToken cancellationToken = default);
|
||||
Task DeleteById(TId id,CancellationToken cancellationToken = default);
|
||||
Task<T?> GetById(TId id,CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace VizhTalk.BuildingBlocks.Domain;
|
||||
using System;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Domain;
|
||||
|
||||
public abstract class TypedIdValueBase<T> : IEquatable<TypedIdValueBase<T>> , ITypeIdValueBase
|
||||
{
|
||||
@@ -35,6 +37,11 @@ public abstract class TypedIdValueBase<T> : IEquatable<TypedIdValueBase<T>> , IT
|
||||
return EqualityComparer<T>.Default.Equals(this.Value, other.Value);
|
||||
}
|
||||
|
||||
public bool Equals(ITypeIdValueBase? other)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static bool operator ==(TypedIdValueBase<T>? obj1, TypedIdValueBase<T>? obj2)
|
||||
{
|
||||
if (object.Equals(obj1, null))
|
||||
|
||||
@@ -31,6 +31,7 @@ public abstract class ValueObject : IEquatable<ValueObject>
|
||||
return !(obj1 == obj2);
|
||||
}
|
||||
|
||||
|
||||
public bool Equals(ValueObject? obj)
|
||||
{
|
||||
return Equals(obj as object);
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using VizhTalk.BuildingBlocks.Application;
|
||||
using VizhTalk.BuildingBlocks.Application.Events;
|
||||
using VizhTalk.BuildingBlocks.Application.Outbox;
|
||||
using VizhTalk.BuildingBlocks.Domain;
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
using VizhTalk.BuildingBlocks.Application.Configuration.Commnad;
|
||||
using VizhTalk.BuildingBlocks.Application.Contract;
|
||||
using VizhTalk.BuildingBlocks.Application;
|
||||
using VizhTalk.BuildingBlocks.Application.Configuration.Commnad;
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Infrastructure.DomainEventsDispatching;
|
||||
@@ -8,12 +8,12 @@ public class UnitOfWorkCommandHandlerDecorator<TCommand> : ICommandHandler<TComm
|
||||
where TCommand : ICommand
|
||||
{
|
||||
private readonly ICommandHandler<TCommand> _decorated;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IUnitOfWorkBase _unitOfWork;
|
||||
private readonly IDomainEventsDispatcher _domainEventsDispatcher;
|
||||
|
||||
public UnitOfWorkCommandHandlerDecorator(
|
||||
ICommandHandler<TCommand> decorated,
|
||||
IUnitOfWork unitOfWork,
|
||||
IUnitOfWorkBase unitOfWork,
|
||||
IDomainEventsDispatcher domainEventsDispatcher)
|
||||
{
|
||||
_decorated = decorated;
|
||||
@@ -34,12 +34,12 @@ public class UnitOfWorkCommandHandlerDecorator<TCommand,TResponse> : ICommandHan
|
||||
where TCommand : ICommand<TResponse>
|
||||
{
|
||||
private readonly ICommandHandler<TCommand, TResponse> _decorated;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IUnitOfWorkBase _unitOfWork;
|
||||
private readonly IDomainEventsDispatcher _domainEventsDispatcher;
|
||||
|
||||
public UnitOfWorkCommandHandlerDecorator(
|
||||
ICommandHandler<TCommand, TResponse> decorated,
|
||||
IUnitOfWork unitOfWork,
|
||||
IUnitOfWorkBase unitOfWork,
|
||||
IDomainEventsDispatcher domainEventsDispatcher)
|
||||
{
|
||||
_decorated = decorated;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Humanizer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using System.Reflection;
|
||||
using VizhTalk.BuildingBlocks.Domain;
|
||||
|
||||
@@ -7,11 +8,16 @@ namespace VizhTalk.BuildingBlocks.Infrastructure.EF.Helpers
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static ModelBuilder FindEntities(this ModelBuilder modelBuilder)
|
||||
public static ModelBuilder FindEntities(this ModelBuilder modelBuilder, Assembly assembly)
|
||||
{
|
||||
var entityTypes = typeof(Entity<>).Assembly
|
||||
.GetTypes()
|
||||
.Where(t => t.IsClass && !t.IsAbstract && typeof(Entity<>).IsAssignableFrom(t));
|
||||
var entityTypes = assembly
|
||||
.GetTypes()
|
||||
.Where(t =>
|
||||
t.IsClass &&
|
||||
!t.IsAbstract &&
|
||||
t.BaseType != null &&
|
||||
t.BaseType.IsGenericType &&
|
||||
t.BaseType.GetGenericTypeDefinition() == typeof(Entity<>));
|
||||
|
||||
foreach (var type in entityTypes)
|
||||
modelBuilder.Entity(type);
|
||||
@@ -22,8 +28,7 @@ namespace VizhTalk.BuildingBlocks.Infrastructure.EF.Helpers
|
||||
{
|
||||
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||
{
|
||||
var tableName = entityType.ClrType.Name.Pluralize();
|
||||
modelBuilder.Entity(entityType.ClrType).ToTable(tableName);
|
||||
entityType.SetTableName(entityType.DisplayName().Pluralize());
|
||||
}
|
||||
return modelBuilder;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Infrastructure.Exceptions
|
||||
{
|
||||
public class EntityNotFoundException(string name) : Exception(name)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace VizhTalk.BuildingBlocks.Infrastructure;
|
||||
|
||||
public interface IUnitOfWork
|
||||
{
|
||||
Task<int> CommitAsync(
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VizhTalk.BuildingBlocks.Domain;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure.Exceptions;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Infrastructure
|
||||
{
|
||||
public class RepositoryBase<T, TId> : IRepositoryBase<T, TId>
|
||||
where T : Entity<TId> where TId : ITypeIdValueBase
|
||||
|
||||
{
|
||||
private readonly DbContext _dbContext;
|
||||
|
||||
public RepositoryBase(DbContext dbContext)
|
||||
{
|
||||
this._dbContext = dbContext;
|
||||
}
|
||||
public async Task<T> AddAsync(T entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await _dbContext.Set<T>().AddAsync(entity, cancellationToken);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(T entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await DeleteById(entity.Id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task DeleteById(TId id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var set = _dbContext.Set<T>();
|
||||
var entity = await set.FirstOrDefaultAsync(x => x.Id.Equals(id));
|
||||
if (entity == null)
|
||||
throw new EntityNotFoundException(set.EntityType.Name);
|
||||
|
||||
entity.SetDeleted(true);
|
||||
}
|
||||
|
||||
public async Task<T?> GetById(TId id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var set = _dbContext.Set<T>();
|
||||
return await set.FirstOrDefaultAsync(x => x.Id.Equals(id));
|
||||
}
|
||||
|
||||
public Task UpdateAsync(T entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var set = _dbContext.Set<T>();
|
||||
set.Update(entity);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using Microsoft.Data.SqlClient;
|
||||
using System.Data;
|
||||
using VizhTalk.BuildingBlocks.Application.Data;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Infrastructure;
|
||||
|
||||
public class SqlConnectionFactory : ISqlConnectionFactory
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
private IDbConnection _connection;
|
||||
|
||||
public SqlConnectionFactory(string connectionString)
|
||||
{
|
||||
this._connectionString = connectionString;
|
||||
}
|
||||
|
||||
public IDbConnection GetOpenConnection()
|
||||
{
|
||||
if (this._connection == null || this._connection.State != ConnectionState.Open)
|
||||
{
|
||||
this._connection = new SqlConnection(_connectionString);
|
||||
this._connection.Open();
|
||||
}
|
||||
|
||||
return this._connection;
|
||||
}
|
||||
|
||||
public IDbConnection CreateNewConnection()
|
||||
{
|
||||
var connection = new SqlConnection(_connectionString);
|
||||
connection.Open();
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
public string GetConnectionString()
|
||||
{
|
||||
return _connectionString;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this._connection != null && this._connection.State == ConnectionState.Open)
|
||||
{
|
||||
this._connection.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-2
@@ -1,14 +1,15 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using VizhTalk.BuildingBlocks.Application;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure.DomainEventsDispatching;
|
||||
|
||||
namespace VizhTalk.BuildingBlocks.Infrastructure;
|
||||
|
||||
public class UnitOfWork : IUnitOfWork
|
||||
public class UnitOfWorkBase : IUnitOfWorkBase
|
||||
{
|
||||
private readonly DbContext _context;
|
||||
private readonly IDomainEventsDispatcher _domainEventsDispatcher;
|
||||
|
||||
public UnitOfWork(
|
||||
public UnitOfWorkBase(
|
||||
DbContext context,
|
||||
IDomainEventsDispatcher domainEventsDispatcher)
|
||||
{
|
||||
@@ -23,4 +24,10 @@ public class UnitOfWork : IUnitOfWork
|
||||
|
||||
return await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
_context.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -20,4 +20,8 @@
|
||||
<ProjectReference Include="..\VizhTalk.BuildingBlocks.Application\VizhTalk.BuildingBlocks.Application.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="EF\Configuration\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using VizhTalk.Grpc.Learning.Language;
|
||||
|
||||
namespace VizhTalk.Gateway.Web.BFF.Mutations;
|
||||
|
||||
public class LanguageMutation(LanguageGrpc.LanguageGrpcClient client)
|
||||
{
|
||||
[GraphQLName("CreateLanguage")]
|
||||
public async Task<LanguageDTO> CreateLanguage(CreateLanguageRequest model)
|
||||
=> await client.CreateAsync(model);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using VizhTalk.Gateway.Web.BFF.Mutations;
|
||||
using VizhTalk.Gateway.Web.BFF.Queries;
|
||||
using VizhTalk.Grpc.Learning.Language;
|
||||
|
||||
@@ -8,10 +9,11 @@ builder.Services.AddGrpcClient<LanguageGrpc.LanguageGrpcClient>(o =>
|
||||
});
|
||||
|
||||
builder.Services.AddScoped<LanguageQuery>();
|
||||
builder.Services.AddScoped<LanguageMutation>();
|
||||
|
||||
builder.AddGraphQL()
|
||||
.AddQueryType<LanguageQuery>();
|
||||
|
||||
.AddQueryType<LanguageQuery>()
|
||||
.AddMutationType<LanguageMutation>();
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapGraphQL();
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
|
||||
namespace VizhTalk.Gateway.Web.BFF.Queries
|
||||
{
|
||||
public class LanguageQuery(LanguageGrpc.LanguageGrpcClient languageGrpcClient)
|
||||
public class LanguageQuery(LanguageGrpc.LanguageGrpcClient client)
|
||||
{
|
||||
[GraphQLName("Languages")]
|
||||
public async Task<GetAllLanguageReply> GetAll()
|
||||
{
|
||||
return await languageGrpcClient.GetAllAsync(new Empty());
|
||||
}
|
||||
[GraphQLName("Language")]
|
||||
public async Task<Language> GetLanguageByTitle(GetLanguageByTitleRequest request)
|
||||
=> await languageGrpcClient.GetLanguageByTitleAsync(request);
|
||||
public async Task<GetAllLanguageDTO> GetAllLanguage()
|
||||
=> await client.GetAllAsync(new GetAllLanguageRequest());
|
||||
|
||||
[GraphQLName("LanguageByTitle")]
|
||||
public async Task<LanguageDTO> GetLanguageByTitle(GetLanguageByTitleRequest request)
|
||||
=> await client.GetByTitleAsync(request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
using VizhTalk.Grpc.Learning.Language;
|
||||
|
||||
namespace VizhTalk.Learning.Application.CommandHandlers.Commands;
|
||||
|
||||
public record CreateLanguageCommand(CreateLanguageRequest model) : ICommand<LanguageDTO>;
|
||||
public record UpdateLanguageCommand(UpdateLanguageRequest model) : ICommand;
|
||||
@@ -0,0 +1,35 @@
|
||||
using Mapster;
|
||||
using VizhTalk.BuildingBlocks.Application.Configuration.Commnad;
|
||||
using VizhTalk.Grpc.Learning.Language;
|
||||
using VizhTalk.Learning.Application.CommandHandlers.Commands;
|
||||
using VizhTalk.Learning.Domain.Entities;
|
||||
using VizhTalk.Learning.Domain.ValueObjects;
|
||||
|
||||
namespace VizhTalk.Learning.Application.CommandHandlers
|
||||
{
|
||||
public class CreateLanguageCommandHandler(IUnitOfWork unitOfWork) : ICommandHandler<CreateLanguageCommand, LanguageDTO>
|
||||
{
|
||||
public async Task<LanguageDTO> Handle(CreateLanguageCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var language = Language.CreateNew(new LanguageTitle(request.model.Title));
|
||||
await unitOfWork.Language.AddAsync(language, cancellationToken);
|
||||
return language.Adapt<LanguageDTO>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateLanguageCommandHandler(IUnitOfWork unitOfWork) : ICommandHandler<UpdateLanguageCommand>
|
||||
{
|
||||
public Task Handle(UpdateLanguageCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure;
|
||||
using VizhTalk.BuildingBlocks.Application;
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
|
||||
namespace VizhTalk.Learning.Application;
|
||||
namespace VizhTalk.Learning.Infrastructure.Configuration;
|
||||
|
||||
public interface ILearningModule : IExecutor
|
||||
{
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using VizhTalk.BuildingBlocks.Application;
|
||||
using VizhTalk.Learning.Domain.Repositories;
|
||||
|
||||
namespace VizhTalk.Learning.Application;
|
||||
|
||||
public interface IUnitOfWork : IUnitOfWorkBase
|
||||
{
|
||||
public ILanguageRepository Language { get; }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Mapster;
|
||||
using VizhTalk.Grpc.Learning.Language;
|
||||
using VizhTalk.Learning.Domain.Entities;
|
||||
|
||||
namespace VizhTalk.Learning.Application.Mappers
|
||||
{
|
||||
public class MapperConfig
|
||||
{
|
||||
public static void Process()
|
||||
{
|
||||
|
||||
var config = TypeAdapterConfig<Language, LanguageDTO>.NewConfig()
|
||||
.Map(x => x.Title, des => des.Title.Value)
|
||||
.Map(x=>x.Id, des=> des.Id == null ? 0 : des.Id.Value);
|
||||
|
||||
config.Compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
using VizhTalk.Grpc.Learning.Language;
|
||||
|
||||
namespace VizhTalk.Learning.Application.QueryHandlers.Queries;
|
||||
|
||||
public class GetAllLanguageQuery : IQuery<GetAllLanguageDTO>;
|
||||
public class GetLanguageByTitleQuery : IQuery<LanguageDTO>;
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VizhTalk.BuildingBlocks.Application\VizhTalk.BuildingBlocks.Application.csproj" />
|
||||
<ProjectReference Include="..\VizhTalk.BuildingBlocks.Infrastructure\VizhTalk.BuildingBlocks.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\VizhTalk.Learning.Domain\VizhTalk.Learning.Domain.csproj" />
|
||||
<ProjectReference Include="..\VizhTalk.Services.Grpc.Learning\VizhTalk.Grpc.Learning.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -6,6 +6,16 @@ namespace VizhTalk.Learning.Domain.Entities;
|
||||
|
||||
public class Language : Entity<LanguageId>, IAggregateRoot
|
||||
{
|
||||
public Language()
|
||||
{
|
||||
// only EF
|
||||
}
|
||||
private Language(LanguageTitle title)
|
||||
{
|
||||
Title = title;
|
||||
}
|
||||
public LanguageTitle Title { get; private set; }
|
||||
|
||||
|
||||
public static Language CreateNew(LanguageTitle title)
|
||||
=> new(title);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using VizhTalk.BuildingBlocks.Domain;
|
||||
using VizhTalk.Learning.Domain.Entities;
|
||||
using VizhTalk.Learning.Domain.TypeIds;
|
||||
|
||||
namespace VizhTalk.Learning.Domain.Repositories
|
||||
{
|
||||
public interface ILanguageRepository : IRepositoryBase<Language,LanguageId>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,9 @@ using VizhTalk.BuildingBlocks.Domain;
|
||||
|
||||
namespace VizhTalk.Learning.Domain.TypeIds
|
||||
{
|
||||
public class LanguageId : TypedIdValueBase<LanguageId>
|
||||
public class LanguageId : TypedIdValueBase<long>
|
||||
{
|
||||
public LanguageId(LanguageId value) : base(value)
|
||||
public LanguageId(long value) : base(value)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace VizhTalk.Learning.Domain.ValueObjects
|
||||
public LanguageTitle(string title)
|
||||
{
|
||||
Guard.NullOrEmpty(title, nameof(LanguageTitle));
|
||||
Guard.MaxLength(title, nameof(LanguageTitle), 60);
|
||||
|
||||
Value = title;
|
||||
}
|
||||
public string Value { get; set; }
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VizhTalk.Learning.Application;
|
||||
using VizhTalk.Learning.Domain.Entities;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.Configuration
|
||||
{
|
||||
@@ -12,5 +13,6 @@ namespace VizhTalk.Learning.Infrastructure.Configuration
|
||||
{
|
||||
public static Assembly Infrastructure = typeof(LearningStartup).Assembly;
|
||||
public static Assembly Application = typeof(ILearningModule).Assembly;
|
||||
public static Assembly Domain = typeof(Language).Assembly;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Data;
|
||||
using VizhTalk.BuildingBlocks.Application.Configuration.Commnad;
|
||||
using VizhTalk.BuildingBlocks.Application.Configuration.Query;
|
||||
using VizhTalk.BuildingBlocks.Application.Contract;
|
||||
using VizhTalk.BuildingBlocks.Domain;
|
||||
using VizhTalk.BuildingBlocks.Domain.Contract;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure;
|
||||
using VizhTalk.Learning.Application;
|
||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.Configuration;
|
||||
|
||||
@@ -21,19 +25,34 @@ public class LearningModule(IServiceProvider serviceProvider) : ILearningModule
|
||||
|
||||
public async Task<TResult> Execute<TResult>(ICommand<TResult> command, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var handlerType = typeof(ICommandHandler<,>).MakeGenericType(command.GetType());
|
||||
|
||||
var commandType = command.GetType(); // مثلا CreateUserCommand
|
||||
var resultType = commandType.GetInterface(typeof(ICommand<>).Name)!.GetGenericArguments()[0];
|
||||
|
||||
// حالا handlerType میشه:
|
||||
var handlerType = typeof(ICommandHandler<,>).MakeGenericType(commandType, resultType);
|
||||
|
||||
var handler = serviceProvider.GetRequiredService(handlerType);
|
||||
|
||||
dynamic dynamicHandler = handler;
|
||||
dynamic dynamicCommand = command;
|
||||
|
||||
return await dynamicHandler.Handle(dynamicCommand, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<TResult> Execute<TResult>(IQuery<TResult> query, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var handlerType = typeof(ICommandHandler<,>).MakeGenericType(query.GetType());
|
||||
var queryType = query.GetType();
|
||||
var resultType = queryType.GetInterface(typeof(IQuery<>).Name)!.GetGenericArguments()[0];
|
||||
|
||||
// حالا handlerType میشه:
|
||||
var handlerType = typeof(IQueryHandler<,>).MakeGenericType(queryType, resultType);
|
||||
|
||||
var handler = serviceProvider.GetRequiredService(handlerType);
|
||||
|
||||
dynamic dynamicHandler = handler;
|
||||
dynamic dynamicQuery = query;
|
||||
|
||||
return await dynamicHandler.Handle(dynamicQuery, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VizhTalk.Learning.Domain.Entities;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.EF.Configurations
|
||||
{
|
||||
internal class LanguageConfiguration : IEntityTypeConfiguration<Language>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Language> builder)
|
||||
{
|
||||
builder.ToTable(nameof(Language), Schema.Learning);
|
||||
builder.HasKey(x => x.Id);
|
||||
|
||||
builder.Property(x => x.Id)
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasConversion(x => x.Value, x => new Domain.TypeIds.LanguageId(x));
|
||||
|
||||
builder.Property(x => x.Title)
|
||||
.HasConversion(s => s.Value, s => new Domain.ValueObjects.LanguageTitle(s))
|
||||
.HasMaxLength(60);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using VizhTalk.BuildingBlocks.Domain;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure.EF.Helpers;
|
||||
using VizhTalk.Learning.Infrastructure.Configuration;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.EF;
|
||||
|
||||
public class LearningDbContext : DbContext
|
||||
{
|
||||
public LearningDbContext(DbContextOptions<LearningDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
|
||||
}
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.FindEntities()
|
||||
modelBuilder.HasDefaultSchema(Schema.Learning);
|
||||
|
||||
modelBuilder.FindEntities(Assemblies.Domain)
|
||||
.ApplyConfigurationsFromAssembly(Assemblies.Infrastructure, x => x.FullName.Contains("EF.Configurations"))
|
||||
.PluralizeEntities();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.EF
|
||||
{
|
||||
public class Schema
|
||||
{
|
||||
public const string Learning = "Learning";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using VizhTalk.BuildingBlocks.Application;
|
||||
using VizhTalk.BuildingBlocks.Application.Configuration.Commnad;
|
||||
using VizhTalk.BuildingBlocks.Application.Configuration.Query;
|
||||
using VizhTalk.BuildingBlocks.Application.Data;
|
||||
using VizhTalk.BuildingBlocks.Application.Events;
|
||||
using VizhTalk.BuildingBlocks.Application.Outbox;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure.DomainEventsDispatching;
|
||||
using VizhTalk.Learning.Application;
|
||||
using VizhTalk.Learning.Application.Mappers;
|
||||
using VizhTalk.Learning.Infrastructure.Configuration;
|
||||
using VizhTalk.Learning.Infrastructure.EF;
|
||||
using VizhTalk.Learning.Infrastructure.Outbox;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure;
|
||||
|
||||
@@ -16,16 +21,21 @@ public static class LearningStartup
|
||||
{
|
||||
public static void Initialize(this IServiceCollection services, string connectionString)
|
||||
{
|
||||
var domainNotificationsMap = new BiDictionary<string, Type>();
|
||||
|
||||
services.AddDbContext<LearningDbContext>(op =>
|
||||
{
|
||||
op.UseSqlServer(connectionString);
|
||||
});
|
||||
services.AddScoped<DbContext, LearningDbContext>();
|
||||
services.AddScoped<ILearningModule, LearningModule>();
|
||||
services.AddScoped<IExecutor, LearningModule>();
|
||||
services.AddScoped<IUnitOfWorkBase, UnitOfWorkBase>();
|
||||
services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||
services.AddScoped<IDomainEventsAccessor, DomainEventsAccessor>();
|
||||
services.AddScoped<IDomainEventsDispatcher, DomainEventsDispatcher>();
|
||||
services.AddScoped<IDomainNotificationsMapper, DomainNotificationsMapper>();
|
||||
services.AddScoped(sp => domainNotificationsMap);
|
||||
services.Scan(scan => scan.
|
||||
FromAssemblies(Assemblies.Application, Assemblies.Infrastructure)
|
||||
.AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>)), publicOnly: false)
|
||||
@@ -40,7 +50,11 @@ public static class LearningStartup
|
||||
.AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>)), publicOnly: false)
|
||||
.AsImplementedInterfaces()
|
||||
.WithScopedLifetime());
|
||||
services.Decorate(typeof(ICommandHandler<,>), typeof(UnitOfWorkCommandHandlerDecorator<,>));
|
||||
services.Decorate(typeof(ICommandHandler<>), typeof(UnitOfWorkCommandHandlerDecorator<>));
|
||||
|
||||
MapperConfig.Process();
|
||||
|
||||
services.AddScoped(sa =>
|
||||
{
|
||||
var notifications = sa.GetServices<IDomainEventNotification>();
|
||||
@@ -52,9 +66,16 @@ public static class LearningStartup
|
||||
});
|
||||
services.AddScoped<IOutbox>(sa =>
|
||||
{
|
||||
return null; // ToDo
|
||||
return new OutboxAccessor(); // ToDo
|
||||
});
|
||||
|
||||
services.AddScoped<ISqlConnectionFactory>(x => new SqlConnectionFactory(connectionString));
|
||||
}
|
||||
|
||||
public static void UseLearningModule(this IApplicationBuilder app)
|
||||
{
|
||||
using var scope = app.ApplicationServices.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<LearningDbContext>();
|
||||
db.Database.Migrate();
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using VizhTalk.Learning.Infrastructure.EF;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(LearningDbContext))]
|
||||
[Migration("20250901155327_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Learning")
|
||||
.HasAnnotation("ProductVersion", "8.0.19")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Language", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("nvarchar(60)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Languages", "Learning");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: "Learning");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Languages",
|
||||
schema: "Learning",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
Title = table.Column<string>(type: "nvarchar(60)", maxLength: 60, nullable: false),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Languages", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Languages",
|
||||
schema: "Learning");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using VizhTalk.Learning.Infrastructure.EF;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(LearningDbContext))]
|
||||
partial class LearningDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Learning")
|
||||
.HasAnnotation("ProductVersion", "8.0.19")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Language", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("nvarchar(60)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Languages", "Learning");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,12 +15,12 @@ namespace VizhTalk.Learning.Infrastructure.Outbox
|
||||
}
|
||||
public void Add(OutboxMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
}
|
||||
|
||||
public Task Save()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using VizhTalk.BuildingBlocks.Infrastructure;
|
||||
using VizhTalk.Learning.Domain.Entities;
|
||||
using VizhTalk.Learning.Domain.Repositories;
|
||||
using VizhTalk.Learning.Domain.TypeIds;
|
||||
using VizhTalk.Learning.Infrastructure.EF;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure.Repositories
|
||||
{
|
||||
internal class LanguageRepository : RepositoryBase<Language, LanguageId>, ILanguageRepository
|
||||
{
|
||||
public LanguageRepository(LearningDbContext dbContext) : base(dbContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure;
|
||||
using VizhTalk.BuildingBlocks.Infrastructure.DomainEventsDispatching;
|
||||
using VizhTalk.Learning.Application;
|
||||
using VizhTalk.Learning.Domain.Repositories;
|
||||
using VizhTalk.Learning.Infrastructure.EF;
|
||||
using VizhTalk.Learning.Infrastructure.Repositories;
|
||||
|
||||
namespace VizhTalk.Learning.Infrastructure
|
||||
{
|
||||
internal class UnitOfWork(LearningDbContext learningDbContext, IDomainEventsDispatcher domainEventsDispatcher)
|
||||
: UnitOfWorkBase(learningDbContext, domainEventsDispatcher), IUnitOfWork
|
||||
{
|
||||
private ILanguageRepository _language;
|
||||
public ILanguageRepository Language
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_language == null)
|
||||
_language = new LanguageRepository(learningDbContext);
|
||||
|
||||
return _language;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,18 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.19">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.19">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VizhTalk.BuildingBlocks.Infrastructure\VizhTalk.BuildingBlocks.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\VizhTalk.Learning.Application\VizhTalk.Learning.Application.csproj" />
|
||||
|
||||
@@ -2,15 +2,17 @@ using VizhTalk.Learning.Infrastructure;
|
||||
using VizhTalk.Learning.Presentation.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var connectionString = builder.Configuration.GetConnectionString("LearningDB")!;
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddGrpc();
|
||||
|
||||
builder.Services.Initialize("");
|
||||
builder.Services.Initialize(connectionString);
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
app.MapGrpcService<LanguageService>();
|
||||
|
||||
app.UseLearningModule();
|
||||
app.Run();
|
||||
|
||||
@@ -1,27 +1,14 @@
|
||||
using Google.Protobuf.Collections;
|
||||
using Grpc.Core;
|
||||
using Grpc.Core;
|
||||
using VizhTalk.Grpc.Learning.Language;
|
||||
using VizhTalk.Learning.Application.CommandHandlers.Commands;
|
||||
using VizhTalk.Learning.Infrastructure.Configuration;
|
||||
|
||||
namespace VizhTalk.Learning.Presentation.Services;
|
||||
|
||||
public class LanguageService : LanguageGrpc.LanguageGrpcBase
|
||||
public class LanguageService(ILearningModule learningModule) : LanguageGrpc.LanguageGrpcBase
|
||||
{
|
||||
public static GetAllLanguageReply Languages = new GetAllLanguageReply();
|
||||
public LanguageService()
|
||||
public override async Task<LanguageDTO> Create(CreateLanguageRequest request, ServerCallContext context)
|
||||
{
|
||||
Languages.Languages.Add(new Language() { Title = "English" });
|
||||
Languages.Languages.Add(new Language() { Title = "Germany" });
|
||||
Languages.Languages.Add(new Language() { Title = "Persian" });
|
||||
Languages.Languages.Add(new Language() { Title = "Spain" });
|
||||
}
|
||||
public override async Task<GetAllLanguageReply> GetAll(Empty request, ServerCallContext context)
|
||||
{
|
||||
return Languages;
|
||||
}
|
||||
public override async Task<Language> GetLanguageByTitle(GetLanguageByTitleRequest request, ServerCallContext context)
|
||||
{
|
||||
var language = Languages.Languages.FirstOrDefault(x => x.Title == request.Title);
|
||||
|
||||
return language;
|
||||
return await learningModule.Execute(new CreateLanguageCommand(request), context.CancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,16 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.57.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.19">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VizhTalk.Learning.Infrastructure\VizhTalk.Learning.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\VizhTalk.Services.Grpc.Learning\VizhTalk.Grpc.Learning.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema=" " /></VisualStudio></ProjectExtensions>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"LearningDB": "Server=.; Database=VizhTalk.Learning; Trusted_Connection=True; MultipleActiveResultSets=true;TrustServerCertificate=True;"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
|
||||
@@ -4,21 +4,32 @@ option csharp_namespace="VizhTalk.Grpc.Learning.Language";
|
||||
|
||||
package greet;
|
||||
|
||||
message Language {
|
||||
string title = 1;
|
||||
message LanguageDTO {
|
||||
string Id = 1;
|
||||
string title = 2;
|
||||
}
|
||||
|
||||
message GetAllLanguageReply {
|
||||
repeated Language languages = 1;
|
||||
message GetAllLanguageDTO{
|
||||
repeated LanguageDTO language =1;
|
||||
}
|
||||
|
||||
message Empty {}
|
||||
|
||||
message GetLanguageByTitleRequest {
|
||||
string title = 1;
|
||||
message GetAllLanguageRequest{
|
||||
}
|
||||
message GetLanguageByTitleRequest{
|
||||
LanguageDTO Language = 1;
|
||||
}
|
||||
message CreateLanguageRequest{
|
||||
string title = 2;
|
||||
}
|
||||
message UpdateLanguageRequest{
|
||||
string Id = 1;
|
||||
string title = 2;
|
||||
}
|
||||
message Empty{
|
||||
|
||||
}
|
||||
service LanguageGrpc {
|
||||
rpc GetAll (Empty) returns (GetAllLanguageReply);
|
||||
rpc GetLanguageByTitle (GetLanguageByTitleRequest) returns (Language);
|
||||
rpc GetAll (GetAllLanguageRequest) returns (GetAllLanguageDTO);
|
||||
rpc GetByTitle (GetLanguageByTitleRequest) returns (LanguageDTO);
|
||||
rpc Create (CreateLanguageRequest) returns (LanguageDTO);
|
||||
rpc Update (UpdateLanguageRequest) returns (Empty);
|
||||
}
|
||||
Reference in New Issue
Block a user