增加领域事件定义,增加MassTransit 发布事件
continuous-integration/drone/push Build is failing Details

IRC_NewDev
hang 2024-08-19 23:32:53 +08:00
parent 021b32587a
commit 00827e9975
6 changed files with 137 additions and 12 deletions

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Domain.BaseModel
{
/// <summary>
/// 领域实体事件基类
/// </summary>
public abstract class DomainEvent
{
}
public class FailedDomainEvent
{
public Guid Id { get; set; }
public string EventType { get; set; }
public string EventData { get; set; }
public DateTime FailedAt { get; set; }
}
}

View File

@ -1,21 +1,57 @@
using System;
using IRaCIS.Core.Domain.BaseModel;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Cryptography;
namespace IRaCIS.Core.Domain.Models
{
public interface IAggregateRoot;
public interface IEntity<TKey>
{
abstract TKey Id { get; set; }
}
public abstract class Entity : IEntity<Guid>
{
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
#region 领域事件 仅仅允许通过提供的方法进行操作
private readonly List<DomainEvent> _domainEvents = [];
[NotMapped]
public IReadOnlyCollection<DomainEvent> DomainEvents => _domainEvents.AsReadOnly();
public void AddDomainEvent(DomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
}
public void RemoveDomainEvent(DomainEvent domainEvent)
{
_domainEvents.Remove(domainEvent);
}
public void ClearDomainEvents()
{
_domainEvents.Clear();
}
#endregion
}
public interface IEntity<TKey>
{
abstract TKey Id { get; set; }
}
#region 减少实体属性,增加基类

View File

@ -25,7 +25,6 @@
<PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="NewId" Version="4.0.1" />
</ItemGroup>
</Project>

View File

@ -12,13 +12,14 @@ namespace IRaCIS.Core.Infra.EFCore;
public class AuditEntityInterceptor(IUserInfo _userInfo) : SaveChangesInterceptor
{
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
AuditEntities(eventData.Context);
return base.SavingChanges(eventData, result);
}
/// <summary>
/// 在事务提交之前执行
/// </summary>
/// <param name="eventData"></param>
/// <param name="result"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
@ -26,7 +27,12 @@ public class AuditEntityInterceptor(IUserInfo _userInfo) : SaveChangesIntercepto
return base.SavingChangesAsync(eventData, result, cancellationToken);
}
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
AuditEntities(eventData.Context);
return base.SavingChanges(eventData, result);
}
public void AuditEntities(DbContext? context)
{
if (context == null) return;

View File

@ -0,0 +1,59 @@
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using IRaCIS.Core.Domain.Models;
using MassTransit;
namespace IRaCIS.Core.Infra.EFCore.Interceptor
{
public class DispatchDomainEventsInterceptor(IPublishEndpoint publishEndpoint) : SaveChangesInterceptor
{
//领域事件通常与数据变更密切相关。如果在 SaveChanges 之前发布事件,有可能事件发布时的数据状态还没有被持久化到数据库。这可能导致事件消费者看到的是一个不一致的状态
/// <summary>
/// 在事务提交之后分发事件
/// </summary>
/// <param name="eventData"></param>
/// <param name="result"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override async ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result,
CancellationToken cancellationToken = default)
{
await DispatchDomainEvents(eventData.Context);
return await base.SavedChangesAsync(eventData, result, cancellationToken);
}
public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)
{
DispatchDomainEvents(eventData.Context).GetAwaiter().GetResult();
return base.SavedChanges(eventData, result);
}
private async Task DispatchDomainEvents(DbContext? context)
{
if (context == null) return;
var entities = context.ChangeTracker
.Entries<Entity>()
.Where(e => e.Entity.DomainEvents.Any())
.Select(e => e.Entity)
.ToList();
var domainEvents = entities
.SelectMany(e => e.DomainEvents)
.ToList();
entities.ForEach(e => e.ClearDomainEvents());
foreach (var domainEvent in domainEvents)
{
await publishEndpoint.Publish(domainEvent);
}
}
}
}

View File

@ -11,6 +11,7 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="MassTransit" Version="8.2.4" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />