Commit be19a9e3 by 丁松杰

添加部分测试代码

parent d827c767
Showing with 386 additions and 752 deletions
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;
using Product.Api.Domain.ProductTypeAggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Product.Api.Application.CommandHandler
{
public class AddProductTypeCommandHandler : ICommandHandler<Command<AddProductTypeRequest, CommonCommandResponse>, CommonCommandResponse>
{
private readonly IProductTypeRepository _productTypeRepository;
private readonly IUnitOfWork _unitOfWork;
public AddProductTypeCommandHandler(IProductTypeRepository productTypeRepository, IUnitOfWork unitOfWork)
{
_productTypeRepository = productTypeRepository;
_unitOfWork = unitOfWork;
}
public async Task<CommonCommandResponse> Handle(Command<AddProductTypeRequest, CommonCommandResponse> request, CancellationToken cancellationToken)
{
var productType = new Domain.ProductTypeAggregate.ProductType(Guid.NewGuid().ToString("N"), request.Data.Name);
_productTypeRepository.Add(productType);
ProductTypeAddedDomainEvent productTypeAddedDomainEvent = new ProductTypeAddedDomainEvent
{
ProductTypeId = productType.Id,
ProductTypeName = productType.Name
};
productType.AddDomainEvent(productTypeAddedDomainEvent);
var result = await _productTypeRepository.SaveEntitiesAsync();
await _unitOfWork.CompeleteAsync();
return CommonCommandResponse.SuccessResponse;
}
}
}
using Pole.Application.EventBus;
using Pole.Domain;
using Product.Api.Domain.Event;
using Product.Api.Domain.ProductAggregate;
using Product.IntegrationEvents;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Product.Api.Application.DomainEventHandler
{
public class AddDefaultProductWhenProductTypeAdded2DomainEventHandler : IDomainEventHandler<ProductTypeAddedDomainEvent>
{
private readonly IProductRepository _productRepository;
private readonly IEventBus _eventBus;
public AddDefaultProductWhenProductTypeAdded2DomainEventHandler(IProductRepository productRepository, IEventBus eventBus)
{
_productRepository = productRepository;
_eventBus = eventBus;
}
public async Task Handle(ProductTypeAddedDomainEvent request, CancellationToken cancellationToken)
{
Product.Api.Domain.ProductAggregate.Product product = new Product.Api.Domain.ProductAggregate.Product(Guid.NewGuid().ToString("N"), request.ProductTypeName, 100, request.ProductTypeId);
_productRepository.Add(product);
var backId = Guid.NewGuid().ToString("N");
ProductAddedIntegrationEvent productAddedIntegrationEvent = new ProductAddedIntegrationEvent()
{
BacketId = backId,
Price = product.Price,
ProductName = product.Name,
ProductId = product.Id
};
await _eventBus.Publish(productAddedIntegrationEvent, product.Id);
await _productRepository.SaveEntitiesAsync();
}
}
}
using Pole.Domain;
using Product.Api.Domain.Event;
using Product.Api.Domain.ProductAggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Product.Api.Application.DomainEventHandler
{
public class AddDefaultProductWhenProductTypeAddedDomainEventHandler : IDomainEventHandler<ProductTypeAddedDomainEvent>
{
private readonly IProductRepository _productRepository;
public AddDefaultProductWhenProductTypeAddedDomainEventHandler(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public async Task Handle(ProductTypeAddedDomainEvent request, CancellationToken cancellationToken)
{
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.SaveEntitiesAsync();
}
}
}
using Pole.ReliableMessage.Abstraction;
using Product.Api.Application.Query.Abstraction;
using Product.Api.Domain.ProductAggregate;
using Product.IntegrationEvents;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Application.IntegrationEvent.CallBack
{
public class ProductAddedIntegrationEventCallback : IReliableEventCallback<ProductAddedIntegrationEvent, string>
{
private readonly IProductQuery _productQuery;
public ProductAddedIntegrationEventCallback(IProductQuery productQuery)
{
_productQuery = productQuery;
}
public async Task<bool> Callback(string callbackParemeter)
{
return await _productQuery.GetById(callbackParemeter) != null;
}
}
}
using Pole.Core.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Application.Query.Abstraction
{
public interface IProductQuery: IScopedDenpendency
{
Task<Product.Api.Domain.ProductAggregate.Product> GetById(string id);
}
}
using Microsoft.EntityFrameworkCore;
using Product.Api.Application.Query.Abstraction;
using Product.Api.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Application.Query
{
public class EfCoreProductQuery : IProductQuery
{
private readonly ProductDbContext _productDbContext;
public EfCoreProductQuery(ProductDbContext productDbContext)
{
_productDbContext = productDbContext;
}
public Task<Domain.ProductAggregate.Product> GetById(string id)
{
return _productDbContext.Products.FirstOrDefaultAsync(m => m.Id == id);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Orleans;
using Product.Api.Grains.Abstraction;
namespace Product.Api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ProductTypeController : ControllerBase
{
private readonly IClusterClient clusterClient;
public ProductTypeController(IClusterClient clusterClient)
{
this.clusterClient = clusterClient;
}
[HttpGet("AddProductType")]
public void AddProductType(string name = "test")
{
var newId = Guid.NewGuid().ToString("N").ToLower();
var grain = clusterClient.GetGrain<IProductTypeGrain>(newId);
grain.AddProductType(newId, name);
}
}
}
\ No newline at end of file
using Pole.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Domain.ProductAggregate
{
public class Product : Entity, IAggregateRoot
{
public Product(string id ,string name,long price, string productTypeId)
{
Id = id;
Name = name;
Price = price;
ProductTypeId = productTypeId;
}
public string Name { get;private set; }
public long Price { get;private set; }
public string ProductTypeId { get;private set; }
}
}
using Pole.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Domain.ProductTypeAggregate
{
public interface IProductTypeRepository:IRepository<ProductType>
{
}
}
using Pole.Domain;
using Pole.Core.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Domain.ProductTypeAggregate
namespace Product.Api.Domain.AggregatesModel.ProductTypeAggregate
{
public class ProductType : Entity, IAggregateRoot
{
public ProductType(string id,string name)
{
Id = id;
Name = name;
}
public string Name { get;private set; }
public string Name { get; set; }
}
}
using Pole.Domain;
using PoleSample.Apis.Product;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Domain.Event
{
public class ProductTypeAddedDomainEvent: IDomainEvent
{
public string ProductTypeName { get; set; }
public string ProductTypeId { get; set; }
}
}
using Pole.Domain;
using Orleans;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Domain.ProductAggregate
namespace Product.Api.Grains.Abstraction
{
public interface IProductRepository : IRepository<Product>
public interface IProductTypeGrain: IGrainWithStringKey
{
Task<bool> AddProductType(string id, string name);
}
}
using Orleans;
using Product.Api.Domain.AggregatesModel.ProductTypeAggregate;
using Product.Api.Grains.Abstraction;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Grains
{
public class ProductTypeGrain : Grain<ProductType>, IProductTypeGrain
{
public async Task<bool> AddProductType(string id, string name)
{
if (State != null) return false;
ProductType productType = new ProductType
{
Id = id,
Name = name
};
State = productType;
await WriteStateAsync();
return true;
}
}
}
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.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Grpc
{
public class ProductTypeService: PoleSample.Apis.Product.ProductType.ProductTypeBase
{
private readonly ICommandBus _commandBus;
public ProductTypeService(ICommandBus commandBus)
{
_commandBus = commandBus;
}
public override Task<CommonCommandResponse> Add(AddProductTypeRequest request, ServerCallContext context)
{
var cpmmand = new Command<AddProductTypeRequest, CommonCommandResponse>(request);
return _commandBus.Send(cpmmand);
}
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Infrastructure.EntityConfigurations
{
public class ProductEntityTypeEntityTypeConfiguration : IEntityTypeConfiguration<Product.Api.Domain.ProductAggregate.Product>
{
public void Configure(EntityTypeBuilder<Product.Api.Domain.ProductAggregate.Product> builder)
{
builder.ToTable(nameof(Product));
builder.Property(m => m.Id).HasMaxLength(32);
builder.Property(m => m.Name).HasMaxLength(256).IsRequired();
builder.Property(m => m.ProductTypeId).HasMaxLength(32).IsRequired();
builder.Ignore(m => m.DomainEvents);
builder.HasIndex(m => m.ProductTypeId);
builder.HasKey(m => m.Id);
}
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Product.Api.Domain.ProductTypeAggregate;
using Product.Api.Domain.AggregatesModel.ProductTypeAggregate;
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -22,4 +22,5 @@ namespace Product.Api.Infrastructure.EntityConfigurations
builder.HasKey(m => m.Id);
}
}
}
using MediatR;
using Microsoft.EntityFrameworkCore;
using Pole.EntityframeworkCore;
using Microsoft.EntityFrameworkCore;
using Product.Api.Domain.AggregatesModel.ProductTypeAggregate;
using Product.Api.Infrastructure.EntityConfigurations;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
......@@ -11,8 +11,8 @@ namespace Product.Api.Infrastructure
{
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 DbSet<Product.Api.Domain.ProductAggregate.Product> Products { get; set; }
public DbSet<ProductType> ProductTypes { get; set; }
public ProductDbContext(DbContextOptions options) : base(options)
{
......@@ -21,8 +21,9 @@ namespace Product.Api.Infrastructure
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new ProductEntityTypeEntityTypeConfiguration());
//builder.ApplyConfiguration(new ProductEntityTypeEntityTypeConfiguration());
builder.ApplyConfiguration(new ProductTypeEntityTypeConfiguration());
}
}
}
using Pole.Domain.EntityframeworkCore;
using Pole.Domain.UnitOfWork;
using Product.Api.Domain.ProductAggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Infrastructure.Repository
{
public class ProductRepository : EFCoreRepository<Product.Api.Domain.ProductAggregate.Product>, IProductRepository
{
public ProductRepository(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
}
}
using Pole.Domain.EntityframeworkCore;
using Pole.Domain.UnitOfWork;
using Product.Api.Domain.ProductTypeAggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Product.Api.Infrastructure.Repository
{
public class ProductTypeRepository : EFCoreRepository<ProductType>, IProductTypeRepository
{
public ProductTypeRepository(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
}
}
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Product.Api.Infrastructure;
namespace Product.Api.Migrations
{
[DbContext(typeof(ProductDbContext))]
[Migration("20200108090435_init")]
partial class init
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "3.1.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("Product.Api.Domain.ProductAggregate.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("Name")
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.Property<long>("Price")
.HasColumnType("bigint");
b.Property<string>("ProductId")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("Product");
});
#pragma warning restore 612, 618
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace Product.Api.Migrations
{
public partial class Modify_Product_ProductId : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "ProductId",
table: "Product",
maxLength: 32,
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(32)",
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "Product",
maxLength: 256,
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(256)",
oldMaxLength: 256,
oldNullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "ProductId",
table: "Product",
type: "character varying(32)",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldMaxLength: 32);
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "Product",
type: "character varying(256)",
maxLength: 256,
nullable: true,
oldClrType: typeof(string),
oldMaxLength: 256);
}
}
}
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Product.Api.Infrastructure;
namespace Product.Api.Migrations
{
[DbContext(typeof(ProductDbContext))]
[Migration("20200114090656_Add_Product")]
partial class Add_Product
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "3.1.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("Product.Api.Domain.ProductAggregate.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("Name")
.IsRequired()
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.Property<long>("Price")
.HasColumnType("bigint");
b.Property<string>("ProductTypeId")
.IsRequired()
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.HasKey("Id");
b.HasIndex("ProductTypeId");
b.ToTable("Product");
});
modelBuilder.Entity("Product.Api.Domain.ProductTypeAggregate.ProductType", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("Name")
.IsRequired()
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.HasKey("Id");
b.ToTable("ProductType");
});
#pragma warning restore 612, 618
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace Product.Api.Migrations
{
public partial class Add_Product : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Product_ProductId",
table: "Product");
migrationBuilder.DropColumn(
name: "ProductId",
table: "Product");
migrationBuilder.AddColumn<string>(
name: "ProductTypeId",
table: "Product",
maxLength: 32,
nullable: false,
defaultValue: "");
migrationBuilder.CreateTable(
name: "ProductType",
columns: table => new
{
Id = table.Column<string>(maxLength: 32, nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductType", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Product_ProductTypeId",
table: "Product",
column: "ProductTypeId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ProductType");
migrationBuilder.DropIndex(
name: "IX_Product_ProductTypeId",
table: "Product");
migrationBuilder.DropColumn(
name: "ProductTypeId",
table: "Product");
migrationBuilder.AddColumn<string>(
name: "ProductId",
table: "Product",
type: "character varying(32)",
maxLength: 32,
nullable: false,
defaultValue: "");
migrationBuilder.CreateIndex(
name: "IX_Product_ProductId",
table: "Product",
column: "ProductId");
}
}
}
......@@ -9,18 +9,18 @@ using Product.Api.Infrastructure;
namespace Product.Api.Migrations
{
[DbContext(typeof(ProductDbContext))]
[Migration("20200108092455_Modify_Product_ProductId")]
partial class Modify_Product_ProductId
[Migration("20200217053642_Init")]
partial class Init
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "3.1.0")
.HasAnnotation("ProductVersion", "3.1.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("Product.Api.Domain.ProductAggregate.Product", b =>
modelBuilder.Entity("Product.Api.Domain.AggregatesModel.ProductTypeAggregate.ProductType", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
......@@ -31,19 +31,9 @@ namespace Product.Api.Migrations
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.Property<long>("Price")
.HasColumnType("bigint");
b.Property<string>("ProductId")
.IsRequired()
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("Product");
b.ToTable("ProductType");
});
#pragma warning restore 612, 618
}
......
......@@ -2,34 +2,27 @@
namespace Product.Api.Migrations
{
public partial class init : Migration
public partial class Init : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Product",
name: "ProductType",
columns: table => new
{
Id = table.Column<string>(maxLength: 32, nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
Price = table.Column<long>(nullable: false),
ProductId = table.Column<string>(maxLength: 32, nullable: true)
Name = table.Column<string>(maxLength: 256, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Product", x => x.Id);
table.PrimaryKey("PK_ProductType", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Product_ProductId",
table: "Product",
column: "ProductId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Product");
name: "ProductType");
}
}
}
......@@ -15,36 +15,10 @@ namespace Product.Api.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "3.1.0")
.HasAnnotation("ProductVersion", "3.1.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("Product.Api.Domain.ProductAggregate.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("Name")
.IsRequired()
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.Property<long>("Price")
.HasColumnType("bigint");
b.Property<string>("ProductTypeId")
.IsRequired()
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.HasKey("Id");
b.HasIndex("ProductTypeId");
b.ToTable("Product");
});
modelBuilder.Entity("Product.Api.Domain.ProductTypeAggregate.ProductType", b =>
modelBuilder.Entity("Product.Api.Domain.AggregatesModel.ProductTypeAggregate.ProductType", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
......
......@@ -3,30 +3,29 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Protobuf Include="..\..\proto\service\Product\*.proto" AdditionalImportDirs="..\..\proto" GrpcServices="Server" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.26.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0">
<PackageReference Include="Microsoft.Orleans.Client" Version="3.0.2" />
<PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.0" />
<PackageReference Include="Microsoft.Orleans.Core" Version="3.0.2" />
<PackageReference Include="Microsoft.Orleans.OrleansRuntime" Version="3.0.2" />
<PackageReference Include="Microsoft.Orleans.Server" Version="3.0.2" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Pole.Core\Pole.Core.csproj" />
<ProjectReference Include="..\..\..\src\Pole.EventBus.Rabbitmq\Pole.EventBus.Rabbitmq.csproj" />
<ProjectReference Include="..\..\..\src\Pole.EventStorage.PostgreSql\Pole.EventStorage.PostgreSql.csproj" />
<ProjectReference Include="..\..\..\src\Pole.Orleans.Provider.EntityframeworkCore\Pole.Orleans.Provider.EntityframeworkCore.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Pole.Application\Pole.Application.csproj" />
<ProjectReference Include="..\..\..\src\Pole.Domain.EntityframeworkCore\Pole.Domain.EntityframeworkCore.csproj" />
<ProjectReference Include="..\..\..\src\Pole.Domain\Pole.Domain.csproj" />
<ProjectReference Include="..\..\..\src\Pole.Grpc\Pole.Grpc.csproj" />
<ProjectReference Include="..\..\..\src\Pole.ReliableMessage.Masstransit\Pole.ReliableMessage.Masstransit.csproj" />
<ProjectReference Include="..\..\..\src\Pole.ReliableMessage.Storage.Mongodb\Pole.ReliableMessage.Storage.Mongodb.csproj" />
<ProjectReference Include="..\..\..\src\Pole.ReliableMessage\Pole.ReliableMessage.csproj" />
<ProjectReference Include="..\..\intergrationEvents\Product.IntegrationEvents\Product.IntegrationEvents.csproj" />
<Folder Include="Domain\AggregatesModel\ProductAggregate\" />
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="http://json.schemastore.org/appsscript" /></VisualStudio></ProjectExtensions>
</Project>
\ No newline at end of file
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using Pole.Domain.EntityframeworkCore.MediatR;
using Product.Api.Infrastructure;
//using Pole.Domain.EntityframeworkCore.MediatR;
//using Product.Api.Infrastructure;
using System;
using System.Collections.Generic;
using System.IO;
......@@ -11,18 +11,18 @@ using System.Threading.Tasks;
namespace Product.Api
{
public class ProductDbContextDesignFactory : IDesignTimeDbContextFactory<ProductDbContext>
{
public ProductDbContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.Development.json")
.Build();
var optionsBuilder = new DbContextOptionsBuilder<ProductDbContext>()
.UseNpgsql(configuration["postgres:main"]);
//public class ProductDbContextDesignFactory : IDesignTimeDbContextFactory<ProductDbContext>
//{
// public ProductDbContext CreateDbContext(string[] args)
// {
// IConfigurationRoot configuration = new ConfigurationBuilder()
// .SetBasePath(Directory.GetCurrentDirectory())
// .AddJsonFile("appsettings.Development.json")
// .Build();
// var optionsBuilder = new DbContextOptionsBuilder<ProductDbContext>()
// .UseNpgsql(configuration["postgres:main"]);
return new ProductDbContext(optionsBuilder.Options);
}
}
// return new ProductDbContext(optionsBuilder.Options);
// }
//}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Orleans.Hosting;
using Product.Api.Infrastructure;
using Pole.Orleans.Provider.EntityframeworkCore;
using Orleans;
using Product.Api.Grains;
namespace Product.Api
{
......@@ -21,6 +22,12 @@ namespace Product.Api
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseOrleans(siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddEfGrainStorageAsDefault<ProductDbContext>();
});
}
}
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
using GreenPipes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
......@@ -11,9 +5,6 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Npgsql;
using Pole.ReliableMessage.Storage.Mongodb;
using Product.Api.Grpc;
using Product.Api.Infrastructure;
namespace Product.Api
......@@ -31,68 +22,68 @@ 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 =>
options.UseNpgsql(Configuration["postgres:main"]));
services.AddDbContextPool<ProductDbContext>(options =>
options.UseNpgsql(Configuration["postgres:write"]));
services.AddControllers();
//services.AddGrpc(option =>
//{
// if (Environment.IsDevelopment())
// {
// option.EnableDetailedErrors = true;
// }
//});
services.AddGrpc(option =>
{
if (Environment.IsDevelopment())
{
option.EnableDetailedErrors = true;
}
});
services.AddGrpcValidation();
services.AddGrpcRequestValidator(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.AddPole(option =>
//{
// option.AddManageredAssemblies(this.GetType().Assembly);
// option.AutoInjectionDependency();
// option.AutoInjectionCommandHandlersAndDomainEventHandlers();
// option.AddPoleEntityFrameworkCoreDomain();
option.AddPoleReliableMessage(messageOption =>
{
messageOption.AddMasstransitRabbitmq(rabbitoption =>
{
rabbitoption.RabbitMqHostAddress = Configuration["RabbitmqConfig:HostAddress"];
rabbitoption.RabbitMqHostUserName = Configuration["RabbitmqConfig:HostUserName"];
rabbitoption.RabbitMqHostPassword = Configuration["RabbitmqConfig:HostPassword"];
rabbitoption.QueueNamePrefix = Configuration["ServiceName"];
rabbitoption.EventHandlerNameSuffix = "IntegrationEventHandler";
rabbitoption.RetryConfigure =
r =>
{
r.Intervals(TimeSpan.FromSeconds(0.1)
, TimeSpan.FromSeconds(1)
, TimeSpan.FromSeconds(4)
, TimeSpan.FromSeconds(16)
, TimeSpan.FromSeconds(64)
);
r.Ignore<DbUpdateException>(exception =>
{
var sqlException = exception.InnerException as PostgresException;
return sqlException != null && sqlException.SqlState == "23505";
});
};
});
messageOption.AddMongodb(mongodbOption =>
{
mongodbOption.ServiceCollectionName = Configuration["ServiceName"];
mongodbOption.Servers = Configuration.GetSection("MongoConfig:Servers").Get<MongoHost[]>();
});
messageOption.AddEventAssemblies(typeof(Startup).Assembly)
.AddEventHandlerAssemblies(typeof(Startup).Assembly);
messageOption.NetworkInterfaceGatewayAddress = Configuration["ReliableMessageOption:NetworkInterfaceGatewayAddress"];
});
});
// option.AddPoleReliableMessage(messageOption =>
// {
// messageOption.AddMasstransitRabbitmq(rabbitoption =>
// {
// rabbitoption.RabbitMqHostAddress = Configuration["RabbitmqConfig:HostAddress"];
// rabbitoption.RabbitMqHostUserName = Configuration["RabbitmqConfig:HostUserName"];
// rabbitoption.RabbitMqHostPassword = Configuration["RabbitmqConfig:HostPassword"];
// rabbitoption.QueueNamePrefix = Configuration["ServiceName"];
// rabbitoption.EventHandlerNameSuffix = "IntegrationEventHandler";
// rabbitoption.RetryConfigure =
// r =>
// {
// r.Intervals(TimeSpan.FromSeconds(0.1)
// , TimeSpan.FromSeconds(1)
// , TimeSpan.FromSeconds(4)
// , TimeSpan.FromSeconds(16)
// , TimeSpan.FromSeconds(64)
// );
// r.Ignore<DbUpdateException>(exception =>
// {
// var sqlException = exception.InnerException as PostgresException;
// return sqlException != null && sqlException.SqlState == "23505";
// });
// };
// });
// messageOption.AddMongodb(mongodbOption =>
// {
// mongodbOption.ServiceCollectionName = Configuration["ServiceName"];
// mongodbOption.Servers = Configuration.GetSection("MongoConfig:Servers").Get<MongoHost[]>();
// });
// messageOption.AddEventAssemblies(typeof(Startup).Assembly)
// .AddEventHandlerAssemblies(typeof(Startup).Assembly);
// messageOption.NetworkInterfaceGatewayAddress = Configuration["ReliableMessageOption:NetworkInterfaceGatewayAddress"];
// });
//});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UsePoleReliableMessage();
//app.UsePoleReliableMessage();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
......@@ -102,7 +93,8 @@ namespace Product.Api
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<ProductTypeService>();
endpoints.MapDefaultControllerRoute();
//endpoints.MapGrpcService<ProductTypeService>();
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
......
......@@ -8,23 +8,12 @@
}
},
"postgres": {
"main": "Server=192.168.0.248;Port=5432;Username=postgres;Password=comteck2020!@#;Database=Pole_samples_Product;Enlist=True;Timeout=0;Command Timeout=600;Pooling=false;MinPoolSize=20;MaxPoolSize=500;"
"write": "Server=115.238.140.58;Port=5432;Username=postgres;Password=comteck2020!@#;Database=Pole-Product;Enlist=True;Timeout=0;Command Timeout=600;Pooling=false;MinPoolSize=20;MaxPoolSize=500;"
},
"ServiceName": "Product",
"RabbitmqConfig": {
"HostAddress": "rabbitmq://192.168.0.248/",
"HostUserName": "comteck",
"HostPassword": "comteck3030"
},
"MongoConfig": {
"Servers": [
{
"Host": "192.168.0.248",
"Port": "27017"
}
]
},
"ReliableMessageOption": {
"NetworkInterfaceGatewayAddress": "192.168.0.1"
}
}
......@@ -8,28 +8,17 @@
}
},
"postgres": {
"main": "Server=192.168.0.248;Port=5432;Username=postgres;Password=comteck2020!@#;Database=Pole_samples_Product;Enlist=True;Timeout=0;Command Timeout=600;Pooling=false;MinPoolSize=20;MaxPoolSize=500;"
"write": "Server=192.168.0.248;Port=5432;Username=postgres;Password=comteck2020!@#;Database=Pole_samples_Product;Enlist=True;Timeout=0;Command Timeout=600;Pooling=false;MinPoolSize=20;MaxPoolSize=500;"
},
"ServiceName": "Product",
"RabbitmqConfig": {
"HostAddress": "rabbitmq://192.168.0.248/",
"HostUserName": "comteck",
"HostPassword": "comteck3030"
},
"MongoConfig": {
"Servers": [
{
"Host": "192.168.0.248",
"Port": "27017"
}
]
},
"ReliableMessageOption": {
"NetworkInterfaceGatewayAddress": "192.168.0.1"
},
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http2"
}
}
//"Kestrel": {
// "EndpointDefaults": {
// "Protocols": "Http2"
// }
//}
}
using Pole.Core.EventBus.Event;
using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Core.Domain
{
public abstract class Entity
{
string _id;
public virtual string Id
{
get
{
return _id;
}
set
{
_id = value;
}
}
public List<IEvent> DomainEvents { get; private set; }
public bool IsTransient()
{
return string.IsNullOrEmpty(this._id);
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Entity))
return false;
if (Object.ReferenceEquals(this, obj))
return true;
if (this.GetType() != obj.GetType())
return false;
Entity item = (Entity)obj;
if (item.IsTransient() || this.IsTransient())
return false;
else
return item.Id == this.Id;
}
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
public static bool operator ==(Entity left, Entity right)
{
if (Object.Equals(left, null))
return (Object.Equals(right, null)) ? true : false;
else
return left.Equals(right);
}
public static bool operator !=(Entity left, Entity right)
{
return !(left == right);
}
public void AddDomainEvent(IEvent eventItem)
{
DomainEvents = DomainEvents ?? new List<IEvent>();
DomainEvents.Add(eventItem);
}
public void RemoveDomainEvent(IEvent eventItem)
{
if (DomainEvents is null) return;
DomainEvents.Remove(eventItem);
}
public void ClearDomainEvents()
{
DomainEvents?.Clear();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Core.Domain
{
public interface IAggregateRoot { }
}
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Orleans;
using Orleans.Providers;
using Orleans.Runtime;
using Orleans.Storage;
using Pole.Orleans.Provider.EntityframeworkCore.Conventions;
using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Orleans.Provider.EntityframeworkCore
{
public static class GrainStorageServiceCollectionExtensions
{
public static IServiceCollection ConfigureGrainStorageOptions<TContext, TGrain, TEntity>(
this IServiceCollection services,
Action<GrainStorageOptions<TContext, TGrain, TEntity>> configureOptions = null)
where TContext : DbContext
where TGrain : Grain<TEntity>
where TEntity : class, new()
{
return services
.AddSingleton<IPostConfigureOptions<GrainStorageOptions<TContext, TGrain, TEntity>>,
GrainStoragePostConfigureOptions<TContext, TGrain, TEntity, TEntity>>()
.Configure<GrainStorageOptions<TContext, TGrain, TEntity>>(typeof(TGrain).FullName, options =>
{
configureOptions?.Invoke(options);
});
}
public static IServiceCollection ConfigureGrainStorageOptions<TContext, TGrain, TGrainState, TEntity>(
this IServiceCollection services,
Action<GrainStorageOptions<TContext, TGrain, TEntity>> configureOptions = null)
where TContext : DbContext
where TGrain : Grain<TGrainState>
where TGrainState : new()
where TEntity : class
{
return services
.AddSingleton<IPostConfigureOptions<GrainStorageOptions<TContext, TGrain, TEntity>>,
GrainStoragePostConfigureOptions<TContext, TGrain, TGrainState, TEntity>>()
.Configure<GrainStorageOptions<TContext, TGrain, TEntity>>(typeof(TGrain).FullName, options =>
{
configureOptions?.Invoke(options);
});
}
public static IServiceCollection AddEfGrainStorage<TContext>(
this IServiceCollection services,
string providerName = ProviderConstants.DEFAULT_STORAGE_PROVIDER_NAME)
where TContext : DbContext
{
services.TryAddSingleton(typeof(IEntityTypeResolver), typeof(EntityTypeResolver));
services.TryAddSingleton(typeof(IGrainStorageConvention), typeof(GrainStorageConvention));
services.TryAddSingleton(typeof(IGrainStateEntryConfigurator<,,>),
typeof(DefaultGrainStateEntryConfigurator<,,>));
services.AddSingleton(typeof(EntityFrameworkGrainStorage<TContext>));
services.TryAddSingleton<IGrainStorage>(sp =>
sp.GetServiceByName<IGrainStorage>(ProviderConstants.DEFAULT_STORAGE_PROVIDER_NAME));
services.AddSingletonNamedService<IGrainStorage>(providerName,
(sp, name) => sp.GetRequiredService<EntityFrameworkGrainStorage<TContext>>());
return services;
}
}
}
using Microsoft.EntityFrameworkCore;
using Orleans.Hosting;
using Orleans.Providers;
using System;
using System.Collections.Generic;
using System.Text;
namespace Pole.Orleans.Provider.EntityframeworkCore
{
public static class GrainStorageSiloHostBuilderExtensions
{
public static ISiloHostBuilder AddEfGrainStorageAsDefault<TContext>(this ISiloHostBuilder builder)
where TContext : DbContext
{
return builder.AddEfGrainStorage<TContext>(ProviderConstants.DEFAULT_STORAGE_PROVIDER_NAME);
}
public static ISiloHostBuilder AddEfGrainStorage<TContext>(this ISiloHostBuilder builder,
string providerName)
where TContext : DbContext
{
return builder
.ConfigureServices(services => { services.AddEfGrainStorage<TContext>(providerName); });
}
public static ISiloBuilder AddEfGrainStorageAsDefault<TContext>(this ISiloBuilder builder)
where TContext : DbContext
{
return builder.AddEfGrainStorage<TContext>(ProviderConstants.DEFAULT_STORAGE_PROVIDER_NAME);
}
public static ISiloBuilder AddEfGrainStorage<TContext>(this ISiloBuilder builder,
string providerName)
where TContext : DbContext
{
return builder
.ConfigureServices(services => { services.AddEfGrainStorage<TContext>(providerName); });
}
}
}
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