net core+mediatr+EF实现事件触发
参考杨中科的教程
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接口,打印的日志如下: