diff --git a/samples/apis/Backet.Api/Application/IntegrationEvent/Handler/JustTestWhenProductAddedIntegrationEventHandler.cs b/samples/apis/Backet.Api/Application/IntegrationEvent/Handler/JustTestWhenProductAddedIntegrationEventHandler.cs deleted file mode 100644 index 2469ef5..0000000 --- a/samples/apis/Backet.Api/Application/IntegrationEvent/Handler/JustTestWhenProductAddedIntegrationEventHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -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 - { - 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 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(); - } - } -} diff --git a/samples/apis/Backet.Api/Backet.Api.csproj b/samples/apis/Backet.Api/Backet.Api.csproj index 4a5489f..75312f8 100644 --- a/samples/apis/Backet.Api/Backet.Api.csproj +++ b/samples/apis/Backet.Api/Backet.Api.csproj @@ -1,38 +1,33 @@ - + netcoreapp3.1 - - - - - - - - - - - - - - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + - - - - - - - + diff --git a/samples/apis/Backet.Api/Controllers/BacketController.cs b/samples/apis/Backet.Api/Controllers/BacketController.cs new file mode 100644 index 0000000..e288b54 --- /dev/null +++ b/samples/apis/Backet.Api/Controllers/BacketController.cs @@ -0,0 +1,30 @@ +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(newId); + grain.AddBacket(backet); + } + } +} \ No newline at end of file diff --git a/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/Backet.cs b/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/Backet.cs index db0182c..9f76529 100644 --- a/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/Backet.cs +++ b/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/Backet.cs @@ -1,4 +1,4 @@ -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 BacketItems { get; private set; } = new List(); public long TotalPrice { get; private set; } } diff --git a/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/BacketItem.cs b/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/BacketItem.cs index bc32338..d86a6fb 100644 --- a/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/BacketItem.cs +++ b/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/BacketItem.cs @@ -1,4 +1,4 @@ -using Pole.Domain; +using Pole.Core.Domain; using System; using System.Collections.Generic; using System.Linq; diff --git a/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/IBacketRepository.cs b/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/IBacketRepository.cs deleted file mode 100644 index 3da10f0..0000000 --- a/samples/apis/Backet.Api/Domain/AggregatesModel/BacketAggregate/IBacketRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -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 - { - } -} diff --git a/samples/apis/Backet.Api/Grains/Abstraction/IBacketGrain.cs b/samples/apis/Backet.Api/Grains/Abstraction/IBacketGrain.cs new file mode 100644 index 0000000..94f369d --- /dev/null +++ b/samples/apis/Backet.Api/Grains/Abstraction/IBacketGrain.cs @@ -0,0 +1,25 @@ +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 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 BacketItems { get; set; } + } +} diff --git a/samples/apis/Backet.Api/Grains/BacketGrain.cs b/samples/apis/Backet.Api/Grains/BacketGrain.cs new file mode 100644 index 0000000..7bfab62 --- /dev/null +++ b/samples/apis/Backet.Api/Grains/BacketGrain.cs @@ -0,0 +1,30 @@ +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, IBacketGrain + { + public async Task 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; + } + } +} diff --git a/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketEntityTypeConfiguration.cs b/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketEntityTypeConfiguration.cs index 282a6cd..8db1f30 100644 --- a/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketEntityTypeConfiguration.cs +++ b/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketEntityTypeConfiguration.cs @@ -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); diff --git a/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketItemEntityTypeConfiguration.cs b/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketItemEntityTypeConfiguration.cs index 0d97721..0cce173 100644 --- a/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketItemEntityTypeConfiguration.cs +++ b/samples/apis/Backet.Api/Infrastructure/EntityConfigurations/BacketItemEntityTypeConfiguration.cs @@ -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); diff --git a/samples/apis/Backet.Api/Infrastructure/Repository/BacketRepository.cs b/samples/apis/Backet.Api/Infrastructure/Repository/BacketRepository.cs deleted file mode 100644 index 1052cbe..0000000 --- a/samples/apis/Backet.Api/Infrastructure/Repository/BacketRepository.cs +++ /dev/null @@ -1,26 +0,0 @@ -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, IBacketRepository - { - public BacketRepository(IServiceProvider serviceProvider) : base(serviceProvider) - { - } - public override async Task Get(string id) - { - var backet = await base.Get(id); - if (backet != null) - { - await _dbContext.Entry(backet).Collection(m => m.BacketItems).LoadAsync(); - } - return backet; - } - } -} diff --git a/samples/apis/Backet.Api/Migrations/20200117083109_Init.Designer.cs b/samples/apis/Backet.Api/Migrations/20200117083109_Init.Designer.cs deleted file mode 100644 index b18e7f0..0000000 --- a/samples/apis/Backet.Api/Migrations/20200117083109_Init.Designer.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -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("UserId") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("Id") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("TotalPrice") - .HasColumnType("bigint"); - - b.HasKey("UserId"); - - b.ToTable("Backet"); - }); - - modelBuilder.Entity("Backet.Api.Domain.AggregatesModel.BacketAggregate.BacketItem", b => - { - b.Property("ProductId") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("BacketUserId") - .HasColumnType("character varying(32)"); - - b.Property("Id") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("Price") - .HasColumnType("bigint"); - - b.Property("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 - } - } -} diff --git a/samples/apis/Backet.Api/Migrations/20200117083456_Modify_Backet_Key.Designer.cs b/samples/apis/Backet.Api/Migrations/20200117083456_Modify_Backet_Key.Designer.cs deleted file mode 100644 index 8b9855b..0000000 --- a/samples/apis/Backet.Api/Migrations/20200117083456_Modify_Backet_Key.Designer.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -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("Id") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("TotalPrice") - .HasColumnType("bigint"); - - b.Property("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("Id") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("BacketId") - .HasColumnType("character varying(32)"); - - b.Property("Price") - .HasColumnType("bigint"); - - b.Property("ProductId") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("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 - } - } -} diff --git a/samples/apis/Backet.Api/Migrations/20200117083456_Modify_Backet_Key.cs b/samples/apis/Backet.Api/Migrations/20200117083456_Modify_Backet_Key.cs deleted file mode 100644 index 29b0c2d..0000000 --- a/samples/apis/Backet.Api/Migrations/20200117083456_Modify_Backet_Key.cs +++ /dev/null @@ -1,185 +0,0 @@ -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( - name: "Id", - table: "BacketItem", - maxLength: 32, - nullable: false, - oldClrType: typeof(string), - oldType: "character varying(32)", - oldMaxLength: 32, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ProductId", - table: "BacketItem", - maxLength: 32, - nullable: true, - oldClrType: typeof(string), - oldType: "character varying(32)", - oldMaxLength: 32); - - migrationBuilder.AddColumn( - name: "BacketId", - table: "BacketItem", - nullable: true); - - migrationBuilder.AlterColumn( - 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( - name: "ProductId", - table: "BacketItem", - type: "character varying(32)", - maxLength: 32, - nullable: false, - oldClrType: typeof(string), - oldMaxLength: 32, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Id", - table: "BacketItem", - type: "character varying(32)", - maxLength: 32, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 32); - - migrationBuilder.AddColumn( - name: "BacketUserId", - table: "BacketItem", - type: "character varying(32)", - nullable: true); - - migrationBuilder.AlterColumn( - 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); - } - } -} diff --git a/samples/apis/Backet.Api/Migrations/20200119013821_Remove_BacketItem_FK_Constraint.Designer.cs b/samples/apis/Backet.Api/Migrations/20200119013821_Remove_BacketItem_FK_Constraint.Designer.cs deleted file mode 100644 index 4d17eb9..0000000 --- a/samples/apis/Backet.Api/Migrations/20200119013821_Remove_BacketItem_FK_Constraint.Designer.cs +++ /dev/null @@ -1,86 +0,0 @@ -// -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("Id") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("TotalPrice") - .HasColumnType("bigint"); - - b.Property("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("Id") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("BacketId") - .IsRequired() - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("Price") - .HasColumnType("bigint"); - - b.Property("ProductId") - .HasColumnType("character varying(32)") - .HasMaxLength(32); - - b.Property("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 - } - } -} diff --git a/samples/apis/Backet.Api/Migrations/20200119013821_Remove_BacketItem_FK_Constraint.cs b/samples/apis/Backet.Api/Migrations/20200119013821_Remove_BacketItem_FK_Constraint.cs deleted file mode 100644 index e1f560b..0000000 --- a/samples/apis/Backet.Api/Migrations/20200119013821_Remove_BacketItem_FK_Constraint.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Backet.Api.Migrations -{ - public partial class Remove_BacketItem_FK_Constraint : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - 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( - name: "BacketId", - table: "BacketItem", - type: "character varying(32)", - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 32); - } - } -} diff --git a/samples/apis/Backet.Api/Migrations/20200119020249_Update_BacketItem_FK_Constraint.cs b/samples/apis/Backet.Api/Migrations/20200119020249_Update_BacketItem_FK_Constraint.cs deleted file mode 100644 index 0e70f20..0000000 --- a/samples/apis/Backet.Api/Migrations/20200119020249_Update_BacketItem_FK_Constraint.cs +++ /dev/null @@ -1,37 +0,0 @@ -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); - } - } -} diff --git a/samples/apis/Backet.Api/Migrations/20200119020249_Update_BacketItem_FK_Constraint.Designer.cs b/samples/apis/Backet.Api/Migrations/20200218022312_Init.Designer.cs similarity index 95% rename from samples/apis/Backet.Api/Migrations/20200119020249_Update_BacketItem_FK_Constraint.Designer.cs rename to samples/apis/Backet.Api/Migrations/20200218022312_Init.Designer.cs index 446f16c..c28226f 100644 --- a/samples/apis/Backet.Api/Migrations/20200119020249_Update_BacketItem_FK_Constraint.Designer.cs +++ b/samples/apis/Backet.Api/Migrations/20200218022312_Init.Designer.cs @@ -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 => diff --git a/samples/apis/Backet.Api/Migrations/20200117083109_Init.cs b/samples/apis/Backet.Api/Migrations/20200218022312_Init.cs similarity index 71% rename from samples/apis/Backet.Api/Migrations/20200117083109_Init.cs rename to samples/apis/Backet.Api/Migrations/20200218022312_Init.cs index 1dcfa26..2d8ce15 100644 --- a/samples/apis/Backet.Api/Migrations/20200117083109_Init.cs +++ b/samples/apis/Backet.Api/Migrations/20200218022312_Init.cs @@ -10,40 +10,50 @@ namespace Backet.Api.Migrations name: "Backet", columns: table => new { + Id = table.Column(maxLength: 32, nullable: false), UserId = table.Column(maxLength: 32, nullable: false), - Id = table.Column(maxLength: 32, nullable: true), TotalPrice = table.Column(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(maxLength: 32, nullable: false), - Id = table.Column(maxLength: 32, nullable: true), + Id = table.Column(maxLength: 32, nullable: false), + ProductId = table.Column(maxLength: 32, nullable: true), ProductName = table.Column(maxLength: 256, nullable: false), Price = table.Column(nullable: false), - BacketUserId = table.Column(nullable: true) + BacketId = table.Column(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) diff --git a/samples/apis/Backet.Api/Migrations/BacketDbContextModelSnapshot.cs b/samples/apis/Backet.Api/Migrations/BacketDbContextModelSnapshot.cs index 50ee5b9..803959c 100644 --- a/samples/apis/Backet.Api/Migrations/BacketDbContextModelSnapshot.cs +++ b/samples/apis/Backet.Api/Migrations/BacketDbContextModelSnapshot.cs @@ -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 => diff --git a/samples/apis/Backet.Api/Program.cs b/samples/apis/Backet.Api/Program.cs index 3bcea34..2d6843d 100644 --- a/samples/apis/Backet.Api/Program.cs +++ b/samples/apis/Backet.Api/Program.cs @@ -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(); + }) + .UseOrleans(siloBuilder => + { + siloBuilder.UseLocalhostClustering(); + siloBuilder.AddEfGrainStorageAsDefault(); }); } } diff --git a/samples/apis/Backet.Api/Startup.cs b/samples/apis/Backet.Api/Startup.cs index 56f2145..19383aa 100644 --- a/samples/apis/Backet.Api/Startup.cs +++ b/samples/apis/Backet.Api/Startup.cs @@ -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(options => - options.UseNpgsql(Configuration["postgres:main"])); + services.AddDbContextPool(options =>options.UseNpgsql(Configuration["postgres:write"])); + services.AddControllers(); - services.AddGrpc(option => - { - if (Environment.IsDevelopment()) - { - option.EnableDetailedErrors = true; - } - }); + services.ConfigureGrainStorageOptions( + 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(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(); - }); - 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!"); diff --git a/samples/apis/Backet.Api/appsettings.Development.json b/samples/apis/Backet.Api/appsettings.Development.json index 8983e0f..34b9d20 100644 --- a/samples/apis/Backet.Api/appsettings.Development.json +++ b/samples/apis/Backet.Api/appsettings.Development.json @@ -1,8 +1,8 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", + "Default": "Debug", + "Microsoft": "Debug", "Microsoft.Hosting.Lifetime": "Information" } } diff --git a/samples/apis/Backet.Api/appsettings.json b/samples/apis/Backet.Api/appsettings.json index 0ccd5c0..e104568 100644 --- a/samples/apis/Backet.Api/appsettings.json +++ b/samples/apis/Backet.Api/appsettings.json @@ -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" + // } + //} } diff --git a/samples/apis/Order.Api/Order.Api.csproj b/samples/apis/Order.Api/Order.Api.csproj index cb7a4e1..c0b3c70 100644 --- a/samples/apis/Order.Api/Order.Api.csproj +++ b/samples/apis/Order.Api/Order.Api.csproj @@ -12,9 +12,27 @@ - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + diff --git a/samples/apis/Order.Api/Program.cs b/samples/apis/Order.Api/Program.cs index ce04e34..860375e 100644 --- a/samples/apis/Order.Api/Program.cs +++ b/samples/apis/Order.Api/Program.cs @@ -18,10 +18,15 @@ namespace Order.Api } public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }) + .UseOrleans(siloBuilder => + { + siloBuilder.UseLocalhostClustering(); + siloBuilder.AddEfGrainStorageAsDefault(); + }); } } diff --git a/samples/apis/Order.Api/Startup.cs b/samples/apis/Order.Api/Startup.cs index b07cbdc..479020c 100644 --- a/samples/apis/Order.Api/Startup.cs +++ b/samples/apis/Order.Api/Startup.cs @@ -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(); - }); - option.AddEventAssemblies(typeof(Startup).Assembly) - .AddEventHandlerAssemblies(typeof(Startup).Assembly); - option.NetworkInterfaceGatewayAddress = Configuration["ReliableMessageOption:NetworkInterfaceGatewayAddress"]; - }); - - services.AddScoped(); - services.AddScoped(); + } // 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(); }); } } diff --git a/samples/apis/Product.Api/Grains/ProductTypeGrain.cs b/samples/apis/Product.Api/Grains/ProductTypeGrain.cs index 19f8d17..af42807 100644 --- a/samples/apis/Product.Api/Grains/ProductTypeGrain.cs +++ b/samples/apis/Product.Api/Grains/ProductTypeGrain.cs @@ -20,7 +20,6 @@ namespace Product.Api.Grains Id = id, Name = name }; - State = productType; Add(productType); await WriteStateAsync(); return true; diff --git a/samples/apis/Product.Api/Startup.cs b/samples/apis/Product.Api/Startup.cs index 4181f7f..8a35308 100644 --- a/samples/apis/Product.Api/Startup.cs +++ b/samples/apis/Product.Api/Startup.cs @@ -25,59 +25,7 @@ namespace Product.Api services.AddDbContextPool(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(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(); - // }); - // 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. diff --git a/src/Pole.Core/Grains/PoleGrain.cs b/src/Pole.Core/Grains/PoleGrain.cs index 0fc0348..f8a3030 100644 --- a/src/Pole.Core/Grains/PoleGrain.cs +++ b/src/Pole.Core/Grains/PoleGrain.cs @@ -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; } } } diff --git a/src/Pole.Orleans.Provider.EntityframeworkCore/Conventions/GrainStorageConvention.cs b/src/Pole.Orleans.Provider.EntityframeworkCore/Conventions/GrainStorageConvention.cs index ada275b..8b1a52d 100644 --- a/src/Pole.Orleans.Provider.EntityframeworkCore/Conventions/GrainStorageConvention.cs +++ b/src/Pole.Orleans.Provider.EntityframeworkCore/Conventions/GrainStorageConvention.cs @@ -258,9 +258,20 @@ namespace Pole.Orleans.Provider.EntityframeworkCore.Conventions if (options.KeyExtSelector == null) throw new GrainStorageConfigurationException($"KeyExtSelector is not defined for " + $"{typeof(GrainStorageOptions).FullName}"); + Func> compiledQuery = null; + if (options.DbSetAccessor != null) + { + var predicate = CreateKeyPredicate(options); + compiledQuery = EF.CompileAsyncQuery((TContext context, string grainKey) + => options.DbSetAccessor(context) + .SingleOrDefault(predicate)); + } + else + { + compiledQuery = CreateCompiledQuery(options); + } + - Func> compiledQuery - = CreateCompiledQuery(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> CreateKeyPredicate( + 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>(equals, stateParam); + } public virtual void SetDefaultKeySelectors( GrainStorageOptions options) where TContext : DbContext diff --git a/src/Pole.Orleans.Provider.EntityframeworkCore/EntityFrameworkGrainStorage.cs b/src/Pole.Orleans.Provider.EntityframeworkCore/EntityFrameworkGrainStorage.cs index da56d53..cfeebfc 100644 --- a/src/Pole.Orleans.Provider.EntityframeworkCore/EntityFrameworkGrainStorage.cs +++ b/src/Pole.Orleans.Provider.EntityframeworkCore/EntityFrameworkGrainStorage.cs @@ -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);