Commit 91952c96 by 丁松杰

添加 efcore grains 关系实体demo 及测试

parent c771ea77
Showing with 226 additions and 783 deletions
using Backet.Api.Domain.AggregatesModel.BacketAggregate;
using Pole.Application.EventBus;
using Pole.Domain.UnitOfWork;
using Pole.ReliableMessage.Abstraction;
using Product.IntegrationEvents;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Backet.Api.Application.IntegrationEvent.Handler
{
public class JustTestWhenProductAddedIntegrationEventHandler : IntegrationEventHandler<ProductAddedIntegrationEvent>
{
private readonly IBacketRepository _backetRepository;
private readonly IUnitOfWork _unitOfWork;
public JustTestWhenProductAddedIntegrationEventHandler(IServiceProvider serviceProvider, IBacketRepository backetRepository, IUnitOfWork unitOfWork) : base(serviceProvider)
{
_backetRepository = backetRepository;
_unitOfWork = unitOfWork;
}
public override async Task Handle(IReliableEventHandlerContext<ProductAddedIntegrationEvent> context)
{
var @event = context.Event;
Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet backet = new Domain.AggregatesModel.BacketAggregate.Backet(@event.BacketId, "1");
backet.AddBacketItem(@event.ProductId, @event.ProductName, @event.Price);
_backetRepository.Add(backet);
await _backetRepository.SaveEntitiesAsync();
await _unitOfWork.CompeleteAsync();
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Migrations\20200117082211_Init.cs" />
<Compile Remove="Migrations\20200117082211_Init.Designer.cs" />
<Compile Remove="Migrations\20200117091659_Set_Backet_BacketItem_IsRequired_false.cs" />
<Compile Remove="Migrations\20200117091659_Set_Backet_BacketItem_IsRequired_false.Designer.cs" />
<Compile Remove="Migrations\20200119012712_Remove_BacketItem_FK_Constraint.cs" />
<Compile Remove="Migrations\20200119012712_Remove_BacketItem_FK_Constraint.Designer.cs" />
<Compile Remove="Migrations\20200119013717_Remove_BacketItem_FK_Constraint.cs" />
<Compile Remove="Migrations\20200119013717_Remove_BacketItem_FK_Constraint.Designer.cs" />
<Compile Remove="Migrations\20200119020005_Update_BacketItem_FK_Constraint.cs" />
<Compile Remove="Migrations\20200119020005_Update_BacketItem_FK_Constraint.Designer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
<PackageReference Include="Grpc.AspNetCore" Version="2.26.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">
<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.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="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.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="..\..\intergrationEvents\Product.IntegrationEvents\Product.IntegrationEvents.csproj" />
<Folder Include="Application\IntegrationEvent\" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Backet.Api.Grains.Abstraction;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Orleans;
namespace Backet.Api.Controllers
{
//[Route("api/[controller]")]
[ApiController]
public class BacketController : ControllerBase
{
private readonly IClusterClient clusterClient;
public BacketController(IClusterClient clusterClient)
{
this.clusterClient = clusterClient;
}
[HttpPost("api/backet/AddBacket")]
public void AddBacket([FromBody]Backet.Api.Grains.Abstraction.BacketDto backet)
{
var newId = "da8a489fa7b4409294ee1b358fbbfba5";
backet.Id = newId;
var grain = clusterClient.GetGrain<IBacketGrain>(newId);
grain.AddBacket(backet);
}
}
}
\ No newline at end of file
using Pole.Domain;
using Pole.Core.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -8,11 +8,6 @@ namespace Backet.Api.Domain.AggregatesModel.BacketAggregate
{
public class Backet : Entity, IAggregateRoot
{
public Backet(string id,string userId)
{
Id = id;
UserId = userId;
}
public void AddBacketItem(string productId, string productName, long Price)
{
BacketItem backetItem = new BacketItem()
......@@ -32,7 +27,7 @@ namespace Backet.Api.Domain.AggregatesModel.BacketAggregate
TotalPrice += item.Price;
}
}
public string UserId { get; private set; }
public string UserId { get; set; }
public List<BacketItem> BacketItems { get; private set; } = new List<BacketItem>();
public long TotalPrice { get; private set; }
}
......
using Pole.Domain;
using Pole.Core.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
......
using Pole.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Backet.Api.Domain.AggregatesModel.BacketAggregate
{
public interface IBacketRepository : IRepository<Backet>
{
}
}
using Orleans;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Backet.Api.Grains.Abstraction
{
public interface IBacketGrain: IGrainWithStringKey
{
Task<bool> AddBacket(BacketDto backet);
}
public class BacketItemDto
{
public string ProductId { get; set; }
public string ProductName { get; set; }
public long Price { get; set; }
}
public class BacketDto
{
public string Id { get; set; }
public string UserId { get; set; }
public List<BacketItemDto> BacketItems { get; set; }
}
}
using Backet.Api.Grains.Abstraction;
using Pole.Core.Grains;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Backet.Api.Grains
{
public class BacketGrain : PoleGrain<Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet>, IBacketGrain
{
public async Task<bool> AddBacket(BacketDto backetDto)
{
if (State != null) return false;
Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet backet = new Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet
{
Id = backetDto.Id,
UserId= backetDto.UserId
};
if (backetDto.BacketItems == null || backetDto.BacketItems.Count == 0) return false;
backetDto.BacketItems.ForEach(item => {
backet.AddBacketItem(item.ProductId, item.ProductName, item.Price);
});
Add(backet);
await WriteStateAsync();
return true;
}
}
}
......@@ -18,6 +18,7 @@ namespace Backet.Api.Infrastructure.EntityConfigurations
builder.HasMany(m => m.BacketItems).WithOne().IsRequired().OnDelete(DeleteBehavior.Cascade).HasForeignKey("BacketId");
builder.Ignore(m => m.DomainEvents);
builder.Ignore(m => m.IsPersisted);
builder.HasKey(m => m.Id);
builder.HasIndex(m => m.UserId);
......
......@@ -20,6 +20,7 @@ namespace Backet.Api.Infrastructure.EntityConfigurations
builder.Property(m => m.BacketId).HasMaxLength(32).IsRequired();
builder.Ignore(m => m.DomainEvents);
builder.Ignore(m => m.IsPersisted);
builder.HasKey(m => m.Id);
builder.HasIndex(m => m.ProductId);
......
using Backet.Api.Domain.AggregatesModel.BacketAggregate;
using Pole.Domain.EntityframeworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Backet.Api.Infrastructure.Repository
{
public class BacketRepository : EFCoreRepository<Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet>, IBacketRepository
{
public BacketRepository(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
public override async Task<Domain.AggregatesModel.BacketAggregate.Backet> Get(string id)
{
var backet = await base.Get(id);
if (backet != null)
{
await _dbContext.Entry(backet).Collection(m => m.BacketItems).LoadAsync();
}
return backet;
}
}
}
// <auto-generated />
using Backet.Api.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Backet.Api.Migrations
{
[DbContext(typeof(BacketDbContext))]
[Migration("20200117083109_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("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", b =>
{
b.Property<string>("UserId")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<long>("TotalPrice")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("Backet");
});
modelBuilder.Entity("Backet.Api.Domain.AggregatesModel.BacketAggregate.BacketItem", b =>
{
b.Property<string>("ProductId")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("BacketUserId")
.HasColumnType("character varying(32)");
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<long>("Price")
.HasColumnType("bigint");
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.HasKey("ProductId");
b.HasIndex("BacketUserId");
b.ToTable("BacketItem");
});
modelBuilder.Entity("Backet.Api.Domain.AggregatesModel.BacketAggregate.BacketItem", b =>
{
b.HasOne("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", null)
.WithMany("BacketItems")
.HasForeignKey("BacketUserId");
});
#pragma warning restore 612, 618
}
}
}
// <auto-generated />
using Backet.Api.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Backet.Api.Migrations
{
[DbContext(typeof(BacketDbContext))]
[Migration("20200117083456_Modify_Backet_Key")]
partial class Modify_Backet_Key
{
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("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<long>("TotalPrice")
.HasColumnType("bigint");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Backet");
});
modelBuilder.Entity("Backet.Api.Domain.AggregatesModel.BacketAggregate.BacketItem", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("BacketId")
.HasColumnType("character varying(32)");
b.Property<long>("Price")
.HasColumnType("bigint");
b.Property<string>("ProductId")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("BacketId");
b.HasIndex("ProductId");
b.ToTable("BacketItem");
});
modelBuilder.Entity("Backet.Api.Domain.AggregatesModel.BacketAggregate.BacketItem", b =>
{
b.HasOne("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", null)
.WithMany("BacketItems")
.HasForeignKey("BacketId");
});
#pragma warning restore 612, 618
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace Backet.Api.Migrations
{
public partial class Modify_Backet_Key : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BacketItem_Backet_BacketUserId",
table: "BacketItem");
migrationBuilder.DropPrimaryKey(
name: "PK_BacketItem",
table: "BacketItem");
migrationBuilder.DropIndex(
name: "IX_BacketItem_BacketUserId",
table: "BacketItem");
migrationBuilder.DropPrimaryKey(
name: "PK_Backet",
table: "Backet");
migrationBuilder.DropColumn(
name: "BacketUserId",
table: "BacketItem");
migrationBuilder.AlterColumn<string>(
name: "Id",
table: "BacketItem",
maxLength: 32,
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(32)",
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ProductId",
table: "BacketItem",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(32)",
oldMaxLength: 32);
migrationBuilder.AddColumn<string>(
name: "BacketId",
table: "BacketItem",
nullable: true);
migrationBuilder.AlterColumn<string>(
name: "Id",
table: "Backet",
maxLength: 32,
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(32)",
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AddPrimaryKey(
name: "PK_BacketItem",
table: "BacketItem",
column: "Id");
migrationBuilder.AddPrimaryKey(
name: "PK_Backet",
table: "Backet",
column: "Id");
migrationBuilder.CreateIndex(
name: "IX_BacketItem_BacketId",
table: "BacketItem",
column: "BacketId");
migrationBuilder.CreateIndex(
name: "IX_BacketItem_ProductId",
table: "BacketItem",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Backet_UserId",
table: "Backet",
column: "UserId");
migrationBuilder.AddForeignKey(
name: "FK_BacketItem_Backet_BacketId",
table: "BacketItem",
column: "BacketId",
principalTable: "Backet",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BacketItem_Backet_BacketId",
table: "BacketItem");
migrationBuilder.DropPrimaryKey(
name: "PK_BacketItem",
table: "BacketItem");
migrationBuilder.DropIndex(
name: "IX_BacketItem_BacketId",
table: "BacketItem");
migrationBuilder.DropIndex(
name: "IX_BacketItem_ProductId",
table: "BacketItem");
migrationBuilder.DropPrimaryKey(
name: "PK_Backet",
table: "Backet");
migrationBuilder.DropIndex(
name: "IX_Backet_UserId",
table: "Backet");
migrationBuilder.DropColumn(
name: "BacketId",
table: "BacketItem");
migrationBuilder.AlterColumn<string>(
name: "ProductId",
table: "BacketItem",
type: "character varying(32)",
maxLength: 32,
nullable: false,
oldClrType: typeof(string),
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Id",
table: "BacketItem",
type: "character varying(32)",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldMaxLength: 32);
migrationBuilder.AddColumn<string>(
name: "BacketUserId",
table: "BacketItem",
type: "character varying(32)",
nullable: true);
migrationBuilder.AlterColumn<string>(
name: "Id",
table: "Backet",
type: "character varying(32)",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldMaxLength: 32);
migrationBuilder.AddPrimaryKey(
name: "PK_BacketItem",
table: "BacketItem",
column: "ProductId");
migrationBuilder.AddPrimaryKey(
name: "PK_Backet",
table: "Backet",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_BacketItem_BacketUserId",
table: "BacketItem",
column: "BacketUserId");
migrationBuilder.AddForeignKey(
name: "FK_BacketItem_Backet_BacketUserId",
table: "BacketItem",
column: "BacketUserId",
principalTable: "Backet",
principalColumn: "UserId",
onDelete: ReferentialAction.Restrict);
}
}
}
// <auto-generated />
using Backet.Api.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Backet.Api.Migrations
{
[DbContext(typeof(BacketDbContext))]
[Migration("20200119013821_Remove_BacketItem_FK_Constraint")]
partial class Remove_BacketItem_FK_Constraint
{
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("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<long>("TotalPrice")
.HasColumnType("bigint");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Backet");
});
modelBuilder.Entity("Backet.Api.Domain.AggregatesModel.BacketAggregate.BacketItem", b =>
{
b.Property<string>("Id")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("BacketId")
.IsRequired()
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<long>("Price")
.HasColumnType("bigint");
b.Property<string>("ProductId")
.HasColumnType("character varying(32)")
.HasMaxLength(32);
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("character varying(256)")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("BacketId");
b.HasIndex("ProductId");
b.ToTable("BacketItem");
});
modelBuilder.Entity("Backet.Api.Domain.AggregatesModel.BacketAggregate.BacketItem", b =>
{
b.HasOne("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", null)
.WithMany("BacketItems")
.HasForeignKey("BacketId")
.OnDelete(DeleteBehavior.Restrict);
});
#pragma warning restore 612, 618
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace Backet.Api.Migrations
{
public partial class Remove_BacketItem_FK_Constraint : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "BacketId",
table: "BacketItem",
maxLength: 32,
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(32)",
oldNullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "BacketId",
table: "BacketItem",
type: "character varying(32)",
nullable: true,
oldClrType: typeof(string),
oldMaxLength: 32);
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace Backet.Api.Migrations
{
public partial class Update_BacketItem_FK_Constraint : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BacketItem_Backet_BacketId",
table: "BacketItem");
migrationBuilder.AddForeignKey(
name: "FK_BacketItem_Backet_BacketId",
table: "BacketItem",
column: "BacketId",
principalTable: "Backet",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BacketItem_Backet_BacketId",
table: "BacketItem");
migrationBuilder.AddForeignKey(
name: "FK_BacketItem_Backet_BacketId",
table: "BacketItem",
column: "BacketId",
principalTable: "Backet",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
}
}
......@@ -9,15 +9,15 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Backet.Api.Migrations
{
[DbContext(typeof(BacketDbContext))]
[Migration("20200119020249_Update_BacketItem_FK_Constraint")]
partial class Update_BacketItem_FK_Constraint
[Migration("20200218022312_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("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", b =>
......
......@@ -10,40 +10,50 @@ namespace Backet.Api.Migrations
name: "Backet",
columns: table => new
{
Id = table.Column<string>(maxLength: 32, nullable: false),
UserId = table.Column<string>(maxLength: 32, nullable: false),
Id = table.Column<string>(maxLength: 32, nullable: true),
TotalPrice = table.Column<long>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Backet", x => x.UserId);
table.PrimaryKey("PK_Backet", x => x.Id);
});
migrationBuilder.CreateTable(
name: "BacketItem",
columns: table => new
{
ProductId = table.Column<string>(maxLength: 32, nullable: false),
Id = table.Column<string>(maxLength: 32, nullable: true),
Id = table.Column<string>(maxLength: 32, nullable: false),
ProductId = table.Column<string>(maxLength: 32, nullable: true),
ProductName = table.Column<string>(maxLength: 256, nullable: false),
Price = table.Column<long>(nullable: false),
BacketUserId = table.Column<string>(nullable: true)
BacketId = table.Column<string>(maxLength: 32, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_BacketItem", x => x.ProductId);
table.PrimaryKey("PK_BacketItem", x => x.Id);
table.ForeignKey(
name: "FK_BacketItem_Backet_BacketUserId",
column: x => x.BacketUserId,
name: "FK_BacketItem_Backet_BacketId",
column: x => x.BacketId,
principalTable: "Backet",
principalColumn: "UserId",
onDelete: ReferentialAction.Restrict);
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_BacketItem_BacketUserId",
name: "IX_Backet_UserId",
table: "Backet",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_BacketItem_BacketId",
table: "BacketItem",
column: "BacketId");
migrationBuilder.CreateIndex(
name: "IX_BacketItem_ProductId",
table: "BacketItem",
column: "BacketUserId");
column: "ProductId");
}
protected override void Down(MigrationBuilder migrationBuilder)
......
......@@ -15,7 +15,7 @@ namespace Backet.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("Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet", b =>
......
......@@ -2,11 +2,13 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Backet.Api.Infrastructure;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Orleans;
using Orleans.Hosting;
using Pole.Orleans.Provider.EntityframeworkCore;
namespace Backet.Api
{
public class Program
......@@ -21,6 +23,11 @@ namespace Backet.Api
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseOrleans(siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddEfGrainStorageAsDefault<BacketDbContext>();
});
}
}
......@@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
using Backet.Api.Grains;
using Backet.Api.Infrastructure;
using GreenPipes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
......@@ -12,8 +12,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Npgsql;
using Pole.ReliableMessage.Storage.Mongodb;
using Pole.Orleans.Provider.EntityframeworkCore;
namespace Backet.Api
{
......@@ -30,68 +29,22 @@ namespace Backet.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<BacketDbContext>(options =>
options.UseNpgsql(Configuration["postgres:main"]));
services.AddDbContextPool<BacketDbContext>(options =>options.UseNpgsql(Configuration["postgres:write"]));
services.AddControllers();
services.AddGrpc(option =>
{
if (Environment.IsDevelopment())
{
option.EnableDetailedErrors = true;
}
});
services.ConfigureGrainStorageOptions<BacketDbContext, BacketGrain, Backet.Api.Domain.AggregatesModel.BacketAggregate.Backet>(
options => options
.UseQuery(context => context.Backets.AsNoTracking()
//.Include(box => box.BacketItems)
));
services.AddGrpcValidation();
services.AddGrpcRequestValidator(this.GetType().Assembly);
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"];
});
});
}
// 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();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
......@@ -101,6 +54,7 @@ namespace Backet.Api
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
......
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Default": "Debug",
"Microsoft": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
}
......
......@@ -8,28 +8,17 @@
}
},
"postgres": {
"main": "Server=192.168.0.248;Port=5432;Username=postgres;Password=comteck2020!@#;Database=Pole_samples_Backet;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-Backet;Enlist=True;Timeout=0;Command Timeout=600;Pooling=false;MinPoolSize=20;MaxPoolSize=500;"
},
"ServiceName": "Backet",
"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"
// }
//}
}
......@@ -12,9 +12,27 @@
</ItemGroup>
<ItemGroup>
<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" />
<PackageReference Include="Grpc.AspNetCore" Version="2.26.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.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="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>
</Project>
......@@ -18,10 +18,15 @@ namespace Order.Api
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseOrleans(siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddEfGrainStorageAsDefault<ProductDbContext>();
});
}
}
......@@ -30,27 +30,7 @@ namespace ServiceA
{
services.AddControllers();
services.AddPoleReliableMessage(option =>
{
option.AddMasstransitRabbitmq(rabbitoption =>
{
rabbitoption.RabbitMqHostAddress = Configuration["RabbitmqConfig:HostAddress"];
rabbitoption.RabbitMqHostUserName = Configuration["RabbitmqConfig:HostUserName"];
rabbitoption.RabbitMqHostPassword = Configuration["RabbitmqConfig:HostPassword"];
rabbitoption.QueueNamePrefix = Configuration["ServiceName"];
});
option.AddMongodb(mongodbOption =>
{
mongodbOption.ServiceCollectionName = Configuration["ServiceName"];
mongodbOption.Servers = Configuration.GetSection("MongoConfig:Servers").Get<MongoHost[]>();
});
option.AddEventAssemblies(typeof(Startup).Assembly)
.AddEventHandlerAssemblies(typeof(Startup).Assembly);
option.NetworkInterfaceGatewayAddress = Configuration["ReliableMessageOption:NetworkInterfaceGatewayAddress"];
});
services.AddScoped<IOrderRepository, OrderRepository>();
services.AddScoped<IBankRepository, BankRepository>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......@@ -60,7 +40,7 @@ namespace ServiceA
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapDefaultControllerRoute();
});
}
}
......
......@@ -20,7 +20,6 @@ namespace Product.Api.Grains
Id = id,
Name = name
};
State = productType;
Add(productType);
await WriteStateAsync();
return true;
......
......@@ -25,59 +25,7 @@ namespace Product.Api
services.AddDbContextPool<ProductDbContext>(options =>
options.UseNpgsql(Configuration["postgres:write"]));
services.AddControllers();
//services.AddGrpc(option =>
//{
// if (Environment.IsDevelopment())
// {
// option.EnableDetailedErrors = true;
// }
//});
//services.AddGrpcValidation();
//services.AddGrpcRequestValidator(this.GetType().Assembly);
//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"];
// });
//});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......
......@@ -12,10 +12,12 @@ namespace Pole.Core.Grains
public void Update(TAggregateRoot aggregateRoot)
{
aggregateRoot.IsPersisted = true;
State = aggregateRoot;
}
public void Add(TAggregateRoot aggregateRoot)
{
aggregateRoot.IsPersisted = false;
State = aggregateRoot;
}
}
}
......@@ -258,9 +258,20 @@ namespace Pole.Orleans.Provider.EntityframeworkCore.Conventions
if (options.KeyExtSelector == null)
throw new GrainStorageConfigurationException($"KeyExtSelector is not defined for " +
$"{typeof(GrainStorageOptions<TContext, TGrain, TEntity>).FullName}");
Func<TContext, string, Task<TEntity>> compiledQuery = null;
if (options.DbSetAccessor != null)
{
var predicate = CreateKeyPredicate<TEntity, string>(options);
compiledQuery = EF.CompileAsyncQuery((TContext context, string grainKey)
=> options.DbSetAccessor(context)
.SingleOrDefault(predicate));
}
else
{
compiledQuery = CreateCompiledQuery<TContext, TGrain, TEntity, string>(options);
}
Func<TContext, string, Task<TEntity>> compiledQuery
= CreateCompiledQuery<TContext, TGrain, TEntity, string>(options);
return (TContext context, IAddressable grainRef) =>
{
......@@ -271,7 +282,18 @@ namespace Pole.Orleans.Provider.EntityframeworkCore.Conventions
throw new InvalidOperationException($"Unexpected grain type \"{typeof(TGrain).FullName}\"");
}
private static Expression<Func<TEntity, bool>> CreateKeyPredicate<TEntity, TKey>(
GrainStorageOptions options,
string grainKeyParamName = "__grainKey")
{
ParameterExpression stateParam = Expression.Parameter(typeof(TEntity), "state");
ParameterExpression grainKeyParam = Expression.Parameter(typeof(TKey), grainKeyParamName);
MemberExpression stateKeyParam = Expression.Property(stateParam, options.KeyPropertyName);
BinaryExpression equals = Expression.Equal(grainKeyParam, stateKeyParam);
return Expression.Lambda<Func<TEntity, bool>>(equals, stateParam);
}
public virtual void SetDefaultKeySelectors<TContext, TGrain, TEntity>(
GrainStorageOptions<TContext, TGrain, TEntity> options)
where TContext : DbContext
......
......@@ -2,6 +2,7 @@
using Orleans;
using Orleans.Runtime;
using Orleans.Storage;
using Pole.Core.Domain;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
......@@ -32,6 +33,8 @@ namespace Pole.Orleans.Provider.EntityframeworkCore
public Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState)
{
if (!typeof(Entity).IsAssignableFrom(grainState.Type)) return Task.CompletedTask;
if (!_storage.TryGetValue(grainType, out IGrainStorage storage))
storage = CreateStorage(grainType, grainState);
......
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