net core+mediatr+EF实现事件触发

发布时间 2023-06-05 22:13:25作者: 斯蒂芬斯

参考杨中科的教程

1.先添加接口

using MediatR;

namespace NetOptions.Entities;

public interface IDomainEnvent
{
    void AddNotification(INotification notification);
    IEnumerable<INotification> GetNotifications();
    void ClearNotifications();
}

2.添加抽象基类

using MediatR;

namespace NetOptions.Entities;

public abstract class BaseEntity : IDomainEnvent
{
    private readonly IList<INotification> notifications = new List<INotification>();
    public void AddNotification(INotification notification)
    {
        notifications.Add(notification);
    }

    public void ClearNotifications()
    {
        notifications.Clear();
    }

    public IEnumerable<INotification> GetNotifications()
    {
        return notifications;
    }
}

3 实体类添加相应方法,变成充血模型

using NetOptions.Entities;
using NetOptions.Entities.Events;

public class User : BaseEntity
{
    public long Id{get;set;}
    public string Name{get;set;}

    public User(string name)
    {
        AddNotification(new UserAddNotif(name));
        this.Name = name;
    }

    public void UpdateName(string newName)
    {
        AddNotification(new UpdateUserNotif(this.Name,newName));
        this.Name = newName;
    }
}

4.修改DBContext.添加相应事件

using Microsoft.EntityFrameworkCore;
using NetOptions.Entities;
using MediatR;
using Pomelo.EntityFrameworkCore.MySql;

namespace NetOptions.DbContexts;

public class UserDbContext : DbContext
{
    private readonly IMediator _meditor;

    public UserDbContext(IMediator meditor)
    {
        _meditor = meditor;
    }

    public DbSet<User> Users { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        ServerVersion server =  ServerVersion.Parse("8.0.27");
        optionsBuilder.UseMySql("Data Source=127.0.0.1;port=3306;Initial Catalog=FBTest;user id=root;password=ybdai930728;Character Set=utf8",server);
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }

    public override int SaveChanges()
    {
        var baseDomainNotifs = this.ChangeTracker.Entries<IDomainEnvent>()
            .Where(w => w.Entity.GetNotifications().Any());
        var baseDomainNotifss = baseDomainNotifs.SelectMany(s => s.Entity.GetNotifications()).ToList();
        baseDomainNotifs.ToList().ForEach(c => c.Entity.ClearNotifications());
        foreach(var notif in baseDomainNotifss){
            _meditor.Publish(notif);
        }

        return base.SaveChanges();
    }
}

5,添加action

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NetOptions.DbContexts;

namespace NetOptions.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;
    private readonly UserDbContext _dbContext;

    public WeatherForecastController(ILogger<WeatherForecastController> logger,UserDbContext dbContext)
    {
        _logger = logger;
        _dbContext = dbContext;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        User user = new User("DYB");
        _dbContext.Users.Add(user);
        user.UpdateName("超级塞牙人");
        _dbContext.SaveChanges();

        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

6,添加一些注册

builder.Services.AddMediatR(c=>c.RegisterServicesFromAssembly(Assembly.GetEntryAssembly()));
builder.Services.AddDbContext<UserDbContext>();

7 实现效果 调用 https://localhost:7245/WeatherForecast接口,打印的日志如下: