Commit 5495256f by dingsongjie

完成 unitofwork 部分改造

parent 06f7c1ca
Showing with 246 additions and 188 deletions
using Pole.Application.Cqrs;
using Pole.Application.Command;
using Pole.Application.Cqrs;
using Pole.Grpc.ExtraType;
using PoleSample.Apis.Product;
using System;
......
using NewArchitectureLab.Apps.Product;
using Pole.Application.Command;
using Pole.Application.Cqrs;
using Pole.Domain.UnitOfWork;
using Pole.Grpc.ExtraType;
using PoleSample.Apis.Product;
using Product.Api.Domain.Event;
......@@ -15,9 +17,11 @@ namespace Product.Api.Application.Command.CommandHandler
public class AddProductTypeCommandHandler : ICommandHandler<AddProductTypeCommand, CommonCommandResponse>
{
private readonly IProductTypeRepository _productTypeRepository;
public AddProductTypeCommandHandler(IProductTypeRepository productTypeRepository)
private readonly IUnitOfWorkManager _unitOfWorkManager;
public AddProductTypeCommandHandler(IProductTypeRepository productTypeRepository, IUnitOfWorkManager unitOfWorkManager)
{
_productTypeRepository = productTypeRepository;
_unitOfWorkManager = unitOfWorkManager;
}
public async Task<CommonCommandResponse> Handle(AddProductTypeCommand request, CancellationToken cancellationToken)
{
......@@ -30,9 +34,14 @@ namespace Product.Api.Application.Command.CommandHandler
ProductTypeId = productType.Id,
ProductTypeName = productType.Name
};
productType.AddDomainEvent(productTypeAddedDomainEvent);
var result= await _productTypeRepository.UnitOfWork.CompeleteAsync();
return result;
using(var unitOfWork= await _unitOfWorkManager.BeginUnitOfWork())
{
productType.AddDomainEvent(productTypeAddedDomainEvent);
var result = await _productTypeRepository.SaveEntitiesAsync();
await unitOfWork.CompeleteAsync();
return CommonCommandResponse.SuccessResponse;
}
}
}
}
......@@ -21,7 +21,7 @@ namespace Product.Api.Application.DomainEventHandler
{
Product.Api.Domain.ProductAggregate.Product product = new Product.Api.Domain.ProductAggregate.Product(Guid.NewGuid().ToString("N"), request.ProductTypeName, 100, request.ProductTypeId);
_productRepository.Add(product);
await _productRepository.UnitOfWork.CompeleteAsync();
await _productRepository.SaveEntitiesAsync();
}
}
}
......@@ -21,7 +21,7 @@ namespace Product.Api.Application.DomainEventHandler
{
Product.Api.Domain.ProductAggregate.Product product = new Product.Api.Domain.ProductAggregate.Product(Guid.NewGuid().ToString("N"), request.ProductTypeName, 100, request.ProductTypeId);
_productRepository.Add(product);
await _productRepository.UnitOfWork.CompeleteAsync();
await _productRepository.SaveEntitiesAsync();
}
}
}
using Grpc.Core;
using NewArchitectureLab.Apps.Product;
using Pole.Application.Command;
using Pole.Application.Cqrs;
using Pole.Grpc.ExtraType;
using PoleSample.Apis.Product;
using Product.Api.Application.Command;
using Product.Api.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
......
......@@ -9,11 +9,11 @@ using System.Threading.Tasks;
namespace Product.Api.Infrastructure
{
public class ProductDbContext : DbContextBase
public class ProductDbContext : DbContext
{
public DbSet<Product.Api.Domain.ProductAggregate.Product> Products { get; set; }
public DbSet<Product.Api.Domain.ProductTypeAggregate.ProductType> ProductTypes { get; set; }
public ProductDbContext(DbContextOptions options, IMediator mediator) : base(options, mediator)
public ProductDbContext(DbContextOptions<ProductDbContext> options) : base(options)
{
}
......
using Pole.Domain.UnitOfWork;
using Pole.Domain.EntityframeworkCore;
using Pole.Domain.UnitOfWork;
using Product.Api.Domain.ProductAggregate;
using System;
using System.Collections.Generic;
......@@ -7,35 +8,11 @@ using System.Threading.Tasks;
namespace Product.Api.Infrastructure.Repository
{
public class ProductRepository : IProductRepository
public class ProductRepository : EFCoreRepository<Product.Api.Domain.ProductAggregate.Product>, IProductRepository
{
private readonly ProductDbContext _productDbContext;
public ProductRepository(ProductDbContext productDbContext)
public ProductRepository(IServiceProvider serviceProvider) : base(serviceProvider)
{
_productDbContext = productDbContext;
}
public IUnitOfWork UnitOfWork => _productDbContext;
public void Add(Domain.ProductAggregate.Product entity)
{
_productDbContext.Products.Add(entity);
}
public void Delete(Domain.ProductAggregate.Product entity)
{
throw new NotImplementedException();
}
public Task<Domain.ProductAggregate.Product> Get(string id)
{
throw new NotImplementedException();
}
public void Update(Domain.ProductAggregate.Product entity)
{
throw new NotImplementedException();
}
}
}
using Pole.Domain.UnitOfWork;
using Pole.Domain.EntityframeworkCore;
using Pole.Domain.UnitOfWork;
using Product.Api.Domain.ProductTypeAggregate;
using System;
using System.Collections.Generic;
......@@ -7,34 +8,10 @@ using System.Threading.Tasks;
namespace Product.Api.Infrastructure.Repository
{
public class ProductTypeRepository : IProductTypeRepository
public class ProductTypeRepository : EFCoreRepository<ProductType>, IProductTypeRepository
{
private readonly ProductDbContext _productDbContext;
public ProductTypeRepository(ProductDbContext productDbContext)
{
_productDbContext = productDbContext;
}
public IUnitOfWork UnitOfWork => _productDbContext;
public void Add(ProductType entity)
{
_productDbContext.ProductTypes.Add(entity);
}
public void Delete(ProductType entity)
{
throw new NotImplementedException();
}
public Task<ProductType> Get(string id)
{
throw new NotImplementedException();
}
public void Update(ProductType entity)
public ProductTypeRepository(IServiceProvider serviceProvider) : base(serviceProvider)
{
throw new NotImplementedException();
}
}
}
......@@ -22,9 +22,7 @@ namespace Product.Api
var optionsBuilder = new DbContextOptionsBuilder<ProductDbContext>()
.UseNpgsql(configuration["postgres:main"]);
return new ProductDbContext(optionsBuilder.Options, new NoMediator());
return new ProductDbContext(optionsBuilder.Options);
}
}
}
......@@ -28,17 +28,27 @@ namespace Product.Api
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ProductDbContext>(options =>
services.AddDbContext<ProductDbContext>(options =>
options.UseNpgsql(Configuration["postgres:main"]));
services.AddGrpc(option=> {
services.AddGrpc(option =>
{
if (Environment.IsDevelopment())
{
option.EnableDetailedErrors = true;
}
});
services.AddPoleGrpc(this.GetType().Assembly);
services.AddGrpcValidation();
services.AddGrpcRequestValidator(this.GetType().Assembly);
services.AddPole(option =>
{
option.AddManageredAssemblies(this.GetType().Assembly);
option.AutoInjectionDependency();
option.AutoInjectionCommandHandlersAndDomainEventHandlers();
option.AddPoleEntityFrameworkCoreDomain();
});
services.AddPoleReliableMessage(option =>
{
......
......@@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Application.Cqrs
namespace Pole.Application.Command
{
public interface ICommand<TResponse>:IRequest<TResponse>
{
......
......@@ -5,7 +5,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Pole.Application.Cqrs
namespace Pole.Application.Command
{
public interface ICommandBus
{
......
......@@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Application.Cqrs
namespace Pole.Application.Command
{
public interface ICommandHandler<TCommand,TResult>: IRequestHandler<TCommand, TResult> where TCommand : ICommand<TResult>
{
......
......@@ -4,6 +4,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Pole.Application.Command;
namespace Pole.Application.Cqrs.Internal
{
......
......@@ -6,14 +6,13 @@ using System.Text;
namespace Pole.Application
{
public class PoleApplicationOptions
public class PoleOptions
{
public PoleApplicationOptions(IServiceCollection services, params Assembly [] applicationAssemblies)
public PoleOptions(IServiceCollection services)
{
Services = services;
ApplicationAssemblies = applicationAssemblies;
}
public IServiceCollection Services { get; set; }
public IServiceCollection Services { get;private set; }
public IEnumerable<Assembly> ApplicationAssemblies { get; set; }
}
......
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using Pole.Application;
using Pole.Application.Cqrs;
using Pole.Application.MediatR;
using Pole.Core.DependencyInjection;
......@@ -9,11 +10,16 @@ using System.Linq;
using System.Reflection;
using System.Text;
namespace Pole.Application
namespace Microsoft.Extensions.DependencyInjection
{
public static class PoleApplicationOptionsExtensions
public static class PoleOptionsExtensions
{
public static PoleApplicationOptions AutoInjectionDependency(this PoleApplicationOptions options)
public static PoleOptions AddManageredAssemblies(this PoleOptions options, params Assembly [] assemblies)
{
options.ApplicationAssemblies = assemblies;
return options;
}
public static PoleOptions AutoInjectionDependency(this PoleOptions options)
{
var assemblies = options.ApplicationAssemblies;
......@@ -26,7 +32,7 @@ namespace Pole.Application
return options;
}
public static PoleApplicationOptions AutoInjectionCommandHandlersAndDomainEventHandlers(this PoleApplicationOptions options, ServiceLifetime lifetime = ServiceLifetime.Scoped)
public static PoleOptions AutoInjectionCommandHandlersAndDomainEventHandlers(this PoleOptions options, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
options.Services.AddMediatR(config =>
{
......@@ -35,35 +41,43 @@ namespace Pole.Application
return options;
}
private static void AddScoped(PoleApplicationOptions options, Assembly assembly)
private static void AddScoped(PoleOptions options, Assembly assembly)
{
var queriesImplements = assembly.GetTypes().Where(m => typeof(IScopedDenpendency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract);
foreach (var queriesImplement in queriesImplements)
var implements = assembly.GetTypes().Where(m => typeof(IScopedDenpendency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract);
foreach (var implement in implements)
{
var queriesService = queriesImplement.GetInterfaces().FirstOrDefault();
options.Services.AddScoped(queriesService, queriesImplement);
var services = implement.GetInterfaces();
foreach(var queriesService in services)
{
options.Services.AddScoped(queriesService, implement);
}
}
}
private static void AddTransient(PoleApplicationOptions options, Assembly assembly)
private static void AddTransient(PoleOptions options, Assembly assembly)
{
var queriesImplements = assembly.GetTypes().Where(m => typeof(ITransientDependency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract);
foreach (var queriesImplement in queriesImplements)
var implements = assembly.GetTypes().Where(m => typeof(ITransientDependency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract);
foreach (var implement in implements)
{
var queriesService = queriesImplement.GetInterfaces().FirstOrDefault();
options.Services.AddTransient(queriesService, queriesImplement);
var services = implement.GetInterfaces();
foreach (var queriesService in services)
{
options.Services.AddTransient(queriesService, implement);
}
}
}
private static void AddSingleton(PoleApplicationOptions options, Assembly assembly)
private static void AddSingleton(PoleOptions options, Assembly assembly)
{
var queriesImplements = assembly.GetTypes().Where(m => typeof(ISingleDependency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract);
foreach (var queriesImplement in queriesImplements)
var implements = assembly.GetTypes().Where(m => typeof(ISingleDependency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract);
foreach (var implement in implements)
{
var queriesService = queriesImplement.GetInterfaces().FirstOrDefault();
options.Services.AddSingleton(queriesService, queriesImplement);
var services = implement.GetInterfaces();
foreach (var queriesService in services)
{
options.Services.AddSingleton(queriesService, implement);
}
}
}
}
}
......@@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Application.Cqrs
namespace Pole.Application.Query
{
public interface IQueries: IScopedDenpendency
{
......
......@@ -5,17 +5,18 @@ using MediatR;
using System.Reflection;
using Pole.Application.Cqrs;
using Pole.Application.Cqrs.Internal;
using Microsoft.Extensions.DependencyInjection;
using Pole.Application.Command;
using Pole.Application;
namespace Pole.Application
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddPoleApplication(this IServiceCollection services, Action<PoleApplicationOptions> config, params Assembly[] assemblies)
public static IServiceCollection AddPole(this IServiceCollection services, Action<PoleOptions> config)
{
PoleApplicationOptions poleApplicationOptions = new PoleApplicationOptions(services, assemblies);
PoleOptions poleOptions = new PoleOptions(services);
config(poleApplicationOptions);
config(poleOptions);
services.AddScoped<ICommandBus, DefaultCommandBus>();
......
using MediatR;
using Microsoft.EntityFrameworkCore;
using Pole.Domain;
using Pole.Domain.UnitOfWork;
using Pole.EntityframeworkCore.MediatR;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Pole.EntityframeworkCore
{
public class DbContextBase : DbContext, IUnitOfWork
{
private readonly IMediator _mediator;
public DbContextBase(DbContextOptions options, IMediator mediator) : base(options)
{
_mediator = mediator;
}
public async Task<CompleteResult> CompeleteAsync(CancellationToken cancellationToken = default)
{
var result = CompleteResult.SuccessResult;
await _mediator.DispatchDomainEventsAsync(this);
await base.SaveChangesAsync(cancellationToken);
return result;
}
}
}
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Pole.EntityframeworkCore.MediatR;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Pole.Domain.EntityframeworkCore
{
public class EFCoreRepository<TEntity> : IRepository<TEntity>
where TEntity : Entity, IAggregateRoot
{
protected readonly DbContext _dbContext;
private readonly IMediator _mediator;
public EFCoreRepository(IServiceProvider serviceProvider)
{
var dbContextOptions = serviceProvider.GetRequiredService<DbContextOptions>();
_dbContext = serviceProvider.GetRequiredService(dbContextOptions.ContextType) as DbContext;
_mediator = serviceProvider.GetRequiredService<IMediator>();
}
public void Add(TEntity entity)
{
_dbContext.Set<TEntity>().Add(entity);
}
public void Delete(TEntity entity)
{
_dbContext.Set<TEntity>().Remove(entity);
}
public virtual Task<TEntity> Get(string id)
{
return _dbContext.Set<TEntity>().FirstOrDefaultAsync(m => m.Id == id);
}
public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default)
{
await _mediator.DispatchDomainEventsAsync(_dbContext);
await _dbContext.SaveChangesAsync(cancellationToken);
return true;
}
public void Update(TEntity entity)
{
throw new NotImplementedException();
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
......@@ -10,6 +10,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pole.Application\Pole.Application.csproj" />
<ProjectReference Include="..\Pole.Domain\Pole.Domain.csproj" />
</ItemGroup>
......
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Pole.Application;
using Pole.Domain.EntityframeworkCore;
using Pole.Domain.EntityframeworkCore.UnitOfWork;
using Pole.Domain.UnitOfWork;
using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Domain
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
public static class PoleApplicationOptionsExtension
{
public static IServiceCollection AddPoleDomain(this IServiceCollection service)
public static PoleOptions AddPoleEntityFrameworkCoreDomain(this PoleOptions options)
{
service.AddMediatR();
return service;
options.Services.AddScoped<IUnitOfWorkManager, EntityFrameworkCoreUnitOfWorkManager>();
return options;
}
}
}
using Microsoft.EntityFrameworkCore.Storage;
using Pole.Domain.UnitOfWork;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Pole.Domain.EntityframeworkCore.UnitOfWork
{
public class EntityFrameworkCoreUnitOfWork : IUnitOfWork
{
private readonly IDbContextTransaction _dbContextTransaction;
public EntityFrameworkCoreUnitOfWork(IDbContextTransaction dbContextTransaction)
{
_dbContextTransaction = dbContextTransaction;
}
public Task CompeleteAsync(CancellationToken cancellationToken = default)
{
return _dbContextTransaction.CommitAsync(cancellationToken);
}
public void Dispose()
{
_dbContextTransaction?.Dispose();
}
public Task RollbackAsync(CancellationToken cancellationToken = default)
{
return _dbContextTransaction.RollbackAsync();
}
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Pole.Domain.UnitOfWork;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Pole.Domain.EntityframeworkCore.UnitOfWork
{
public class EntityFrameworkCoreUnitOfWorkManager : IUnitOfWorkManager
{
private readonly DbContext _dbContext;
public EntityFrameworkCoreUnitOfWorkManager(DbContextOptions dbContextOptions, IServiceProvider serviceProvider)
{
_dbContext = serviceProvider.GetRequiredService(dbContextOptions.ContextType) as DbContext;
}
public async Task<IUnitOfWork> BeginUnitOfWork()
{
var transaction = await _dbContext.Database.BeginTransactionAsync();
EntityFrameworkCoreUnitOfWork entityFrameworkCoreUnitOfWork = new EntityFrameworkCoreUnitOfWork(transaction);
return entityFrameworkCoreUnitOfWork;
}
}
}
......@@ -14,7 +14,7 @@ namespace Pole.Domain
void Delete(T entity);
void Add(T entity);
Task<T> Get(string id);
IUnitOfWork UnitOfWork { get; }
Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default);
}
public interface IRepository: IScopedDenpendency
{
......
......@@ -8,8 +8,8 @@ namespace Pole.Domain.UnitOfWork
{
public interface IUnitOfWork : IDisposable
{
//Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
Task<CompleteResult> CompeleteAsync(CancellationToken cancellationToken = default);
Task CompeleteAsync(CancellationToken cancellationToken = default);
Task RollbackAsync(CancellationToken cancellationToken = default);
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Pole.Domain.UnitOfWork
{
public interface IUnitOfWorkManager
{
Task<IUnitOfWork> BeginUnitOfWork();
}
}
......@@ -4,10 +4,11 @@ using System.Text;
namespace Pole.Domain.UnitOfWork
{
public class CompleteResult
public class UnitOfWorkResult
{
public static CompleteResult SuccessResult = new CompleteResult(1, "保存成功");
public CompleteResult(int status, string message)
public static UnitOfWorkResult SuccessResult = new UnitOfWorkResult(1, "保存成功");
public static UnitOfWorkResult FaildResult = new UnitOfWorkResult(1, "保存失败");
public UnitOfWorkResult(int status, string message)
{
Status = status;
Message = message;
......
......@@ -9,9 +9,10 @@ namespace Pole.Grpc.ExtraType
{
public partial class CommonCommandResponse
{
public static implicit operator CommonCommandResponse(CompleteResult domainHandleResult)
public static CommonCommandResponse SuccessResponse = new CommonCommandResponse()
{
return new CommonCommandResponse { Status = domainHandleResult.Status, Message = domainHandleResult.Message };
}
Message = "执行成功",
Status = 1
};
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Pole.Application;
using Pole.Domain;
namespace Pole.Grpc
{
public static class PoleGrpcOptionExtensions
{
public static PoleGrpcOptions AddPoleApplication(this PoleGrpcOptions poleGrpcOptions)
{
poleGrpcOptions.Services.AddPoleApplication(options => {
options.AutoInjectionCommandHandlersAndDomainEventHandlers();
if (poleGrpcOptions.AutoInject)
{
options.AutoInjectionDependency();
}
}, poleGrpcOptions.ApplicationAssemblies.ToArray());
return poleGrpcOptions;
}
public static PoleGrpcOptions AddPoleDomain(this PoleGrpcOptions poleGrpcOptions)
{
poleGrpcOptions.Services.AddPoleDomain();
return poleGrpcOptions;
}
}
}
......@@ -9,13 +9,14 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddPoleGrpc(this IServiceCollection services, params Assembly[] assemblies)
{
PoleGrpcOptions poleGrpcOptions = new PoleGrpcOptions(services, assemblies);
poleGrpcOptions.AddPoleApplication();
poleGrpcOptions.AddPoleDomain();
// poleGrpcOptions.Services.AddGrpcValidation();
return services;
}
//public static IServiceCollection AddPoleGrpc(this IServiceCollection services, params Assembly[] assemblies)
//{
// // PoleGrpcOptions poleGrpcOptions = new PoleGrpcOptions(services, assemblies);
// //poleGrpcOptions.Services.AddGrpcValidation();
// // poleGrpcOptions.Services.addv
// return services;
//}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment