using FreeSql; using FreeSql.DataAnnotations; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; namespace aspnetcore_transaction.Controllers { [ApiController] [Route("")] public class HomeController : ControllerBase { private readonly ILogger _logger; public HomeController(ILogger logger) { _logger = logger; } [HttpGet("1")] //[Transactional] virtual public object Get([FromServices] BaseRepository repoSong, [FromServices] BaseRepository repoDetail, [FromServices] SongRepository repoSong2, [FromServices] SongService serviceSong) { //repoSong.Insert(new Song()); //repoDetail.Insert(new Detail()); //repoSong2.Insert(new Song()); serviceSong.Test1(); return "111"; } [HttpGet("2")] //[Transactional] async virtual public Task GetAsync([FromServices] BaseRepository repoSong, [FromServices] BaseRepository repoDetail, [FromServices] SongRepository repoSong2, [FromServices] SongService serviceSong) { await serviceSong.Test2(); await serviceSong.Test3(); return "111"; } } public class SongService { BaseRepository _repoSong; BaseRepository _repoDetail; SongRepository _repoSong2; public SongService(BaseRepository repoSong, BaseRepository repoDetail, SongRepository repoSong2) { var tb = repoSong.Orm.CodeFirst.GetTableByEntity(typeof(Song)); _repoSong = repoSong; _repoDetail = repoDetail; _repoSong2 = repoSong2; } [Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的 public virtual void Test1() { _repoSong.Insert(new Song()); _repoDetail.Insert(new Detail()); _repoSong2.Insert(new Song()); } [Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的 async public virtual Task Test2() { await _repoSong.InsertAsync(new Song()); await _repoDetail.InsertAsync(new Detail()); await _repoSong2.InsertAsync(new Song()); } [Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的 async public virtual Task Test3() { await _repoSong.InsertAsync(new Song()); await _repoDetail.InsertAsync(new Detail()); await _repoSong2.InsertAsync(new Song()); return "123"; } } public class SongRepository : DefaultRepository { public SongRepository(UnitOfWorkManager uowm) : base(uowm?.Orm, uowm) { } } [Description("123")] public class Song { /// /// 自增 /// [Column(IsIdentity = true)] [Description("自增id")] public int Id { get; set; } public string Title { get; set; } } public class Detail { [Column(IsIdentity = true)] public int Id { get; set; } public int SongId { get; set; } public string Title { get; set; } } public static class IdleBusExtesions { static AsyncLocal AsyncLocalTenantId = new AsyncLocal(); public static IdleBus ChangeTenant(this IdleBus ib, string tenantId) { AsyncLocalTenantId.Value = tenantId; return ib; } public static IFreeSql Get(this IdleBus ib) => ib.Get(AsyncLocalTenantId.Value ?? "default"); public static IBaseRepository GetRepository(this IdleBus ib) where T : class => ib.Get().GetRepository(); static void test() { IdleBus ib = null; //单例注入 var fsql = ib.Get(); //获取当前租户对应的 IFreeSql var fsql00102 = ib.ChangeTenant("00102").Get(); //切换租户,后面的操作都是针对 00102 var songRepository = ib.GetRepository(); var detailRepository = ib.GetRepository(); } public static IServiceCollection AddRepository(this IServiceCollection services, params Assembly[] assemblies) { services.AddScoped(typeof(IBaseRepository<>), typeof(YourDefaultRepository<>)); services.AddScoped(typeof(BaseRepository<>), typeof(YourDefaultRepository<>)); services.AddScoped(typeof(IBaseRepository<,>), typeof(YourDefaultRepository<,>)); services.AddScoped(typeof(BaseRepository<,>), typeof(YourDefaultRepository<,>)); if (assemblies?.Any() == true) foreach (var asse in assemblies) foreach (var repo in asse.GetTypes().Where(a => a.IsAbstract == false && typeof(IBaseRepository).IsAssignableFrom(a))) services.AddScoped(repo); return services; } } class YourDefaultRepository : BaseRepository where T : class { public YourDefaultRepository(IdleBus ib) : base(ib.Get(), null, null) { } } class YourDefaultRepository : BaseRepository where T : class { public YourDefaultRepository(IdleBus ib) : base(ib.Get(), null, null) { } } }