mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	- 增加 UnitOfWorkManager 工作单元管理器,实现多种传播事务;#289
This commit is contained in:
		@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					using FreeSql;
 | 
				
			||||||
 | 
					using FreeSql.DataAnnotations;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace aspnetcore_transaction.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [ApiController]
 | 
				
			||||||
 | 
					    [Route("")]
 | 
				
			||||||
 | 
					    public class HomeController : ControllerBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly ILogger<HomeController> _logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public HomeController(ILogger<HomeController> logger)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _logger = logger;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [HttpGet]
 | 
				
			||||||
 | 
					        //[Transactional]
 | 
				
			||||||
 | 
					        virtual public object Get([FromServices] BaseRepository<Song> repoSong, [FromServices] BaseRepository<Detail> repoDetail, [FromServices] SongRepository repoSong2,
 | 
				
			||||||
 | 
					            [FromServices] SongService serviceSong)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceSong.Test();
 | 
				
			||||||
 | 
					            return "111";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class SongService
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        BaseRepository<Song> _repoSong;
 | 
				
			||||||
 | 
					        BaseRepository<Detail> _repoDetail;
 | 
				
			||||||
 | 
					        SongRepository _repoSong2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public SongService(BaseRepository<Song> repoSong, BaseRepository<Detail> repoDetail, SongRepository repoSong2)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _repoSong = repoSong;
 | 
				
			||||||
 | 
					            _repoDetail = repoDetail;
 | 
				
			||||||
 | 
					            _repoSong2 = repoSong2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Transactional]
 | 
				
			||||||
 | 
					        public virtual void Test()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _repoSong.Insert(new Song());
 | 
				
			||||||
 | 
					            _repoDetail.Insert(new Detail());
 | 
				
			||||||
 | 
					            _repoSong2.Insert(new Song());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class SongRepository : DefaultRepository<Song, int>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public SongRepository(UnitOfWorkManager uowm) : base(uowm?.Orm, uowm) { }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class Song
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [Column(IsIdentity = true)]
 | 
				
			||||||
 | 
					        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; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								Examples/aspnetcore_transaction/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Examples/aspnetcore_transaction/Program.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace aspnetcore_transaction
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class Program
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static void Main(string[] args)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            CreateHostBuilder(args).Build().Run();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IHostBuilder CreateHostBuilder(string[] args) =>
 | 
				
			||||||
 | 
					            Host.CreateDefaultBuilder(args)
 | 
				
			||||||
 | 
					                .ConfigureWebHostDefaults(webBuilder =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    webBuilder.UseStartup<Startup>();
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .UseServiceProviderFactory(new FreeSql.DynamicProxyServiceProviderFactory());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "iisSettings": {
 | 
				
			||||||
 | 
					        "windowsAuthentication": false,
 | 
				
			||||||
 | 
					        "anonymousAuthentication": true,
 | 
				
			||||||
 | 
					        "iisExpress": {
 | 
				
			||||||
 | 
					            "applicationUrl": "http://localhost:35350/",
 | 
				
			||||||
 | 
					            "sslPort": 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "profiles": {
 | 
				
			||||||
 | 
					        "IIS Express": {
 | 
				
			||||||
 | 
					            "commandName": "IISExpress",
 | 
				
			||||||
 | 
					            "launchBrowser": true,
 | 
				
			||||||
 | 
					            "environmentVariables": {
 | 
				
			||||||
 | 
					                "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "dbcontext_01": {
 | 
				
			||||||
 | 
					            "commandName": "Project",
 | 
				
			||||||
 | 
					            "launchBrowser": true,
 | 
				
			||||||
 | 
					            "environmentVariables": {
 | 
				
			||||||
 | 
					                "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "applicationUrl": "http://localhost:35351/"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								Examples/aspnetcore_transaction/Startup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								Examples/aspnetcore_transaction/Startup.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using aspnetcore_transaction.Controllers;
 | 
				
			||||||
 | 
					using FreeSql;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.HttpsPolicy;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace aspnetcore_transaction
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class Startup
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public Startup(IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Configuration = configuration;
 | 
				
			||||||
 | 
					            Fsql = new FreeSql.FreeSqlBuilder()
 | 
				
			||||||
 | 
					                 .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\test_trans.db")
 | 
				
			||||||
 | 
					                 .UseAutoSyncStructure(true)
 | 
				
			||||||
 | 
					                 .UseMonitorCommand(cmd => Trace.WriteLine(cmd.CommandText))
 | 
				
			||||||
 | 
					                 .UseNoneCommandParameter(true)
 | 
				
			||||||
 | 
					                 .Build();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IConfiguration Configuration { get; }
 | 
				
			||||||
 | 
					        public static IFreeSql Fsql { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void ConfigureServices(IServiceCollection services)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddControllersWithViews();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            services.AddSingleton<IFreeSql>(Fsql);
 | 
				
			||||||
 | 
					            services.AddScoped<UnitOfWorkManager>();
 | 
				
			||||||
 | 
					            services.AddFreeRepository(null, typeof(Startup).Assembly);
 | 
				
			||||||
 | 
					            services.AddScoped<SongService>();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
 | 
				
			||||||
 | 
					            Console.OutputEncoding = Encoding.GetEncoding("GB2312");
 | 
				
			||||||
 | 
					            Console.InputEncoding = Encoding.GetEncoding("GB2312");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" });
 | 
				
			||||||
 | 
					            app.UseDeveloperExceptionPage();
 | 
				
			||||||
 | 
					            app.UseRouting();
 | 
				
			||||||
 | 
					            app.UseEndpoints(a => a.MapControllers());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								Examples/aspnetcore_transaction/TransactionalAttribute.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								Examples/aspnetcore_transaction/TransactionalAttribute.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					using FreeSql;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc.Filters;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Data;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace FreeSql
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 使用事务执行,请查看 Program.cs 代码开启动态代理
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [AttributeUsage(AttributeTargets.Method)]
 | 
				
			||||||
 | 
					    public class TransactionalAttribute : DynamicProxyAttribute, IActionFilter
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public Propagation Propagation { get; set; } = Propagation.Requierd;
 | 
				
			||||||
 | 
					        public IsolationLevel? IsolationLevel { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [DynamicProxyFromServices]
 | 
				
			||||||
 | 
					        UnitOfWorkManager _uowManager;
 | 
				
			||||||
 | 
					        IUnitOfWork _uow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override Task Before(DynamicProxyBeforeArguments args) => OnBefore(_uowManager);
 | 
				
			||||||
 | 
					        public override Task After(DynamicProxyAfterArguments args) => OnAfter(args.Exception);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //这里是为了 controller 
 | 
				
			||||||
 | 
					        public void OnActionExecuting(ActionExecutingContext context) => OnBefore(context.HttpContext.RequestServices.GetService(typeof(UnitOfWorkManager)) as UnitOfWorkManager);
 | 
				
			||||||
 | 
					        public void OnActionExecuted(ActionExecutedContext context) => OnAfter(context.Exception);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Task OnBefore(UnitOfWorkManager uowm)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _uow = uowm.Begin(this.Propagation, this.IsolationLevel);
 | 
				
			||||||
 | 
					            return Task.FromResult(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Task OnAfter(Exception ex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (ex == null) _uow.Commit();
 | 
				
			||||||
 | 
					                else _uow.Rollback();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            finally
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _uow.Dispose();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return Task.FromResult(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <TargetFramework>netcoreapp3.1</TargetFramework>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <PackageReference Include="FreeSql.DynamicProxy" Version="1.2.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.0" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
@@ -35,21 +35,21 @@ namespace FreeSql
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public ISelect<T1> Select<T1>() where T1 : class
 | 
					        public ISelect<T1> Select<T1>() where T1 : class
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _resolveDbContext()?.FlushCommand();
 | 
					            _resolveDbContext?.Invoke()?.FlushCommand();
 | 
				
			||||||
            return _originalFsql.Select<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction(false));
 | 
					            return _originalFsql.Select<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction(false));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public ISelect<T1> Select<T1>(object dywhere) where T1 : class => Select<T1>().WhereDynamic(dywhere);
 | 
					        public ISelect<T1> Select<T1>(object dywhere) where T1 : class => Select<T1>().WhereDynamic(dywhere);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IDelete<T1> Delete<T1>() where T1 : class
 | 
					        public IDelete<T1> Delete<T1>() where T1 : class
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _resolveDbContext()?.FlushCommand();
 | 
					            _resolveDbContext?.Invoke()?.FlushCommand();
 | 
				
			||||||
            return _originalFsql.Delete<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
 | 
					            return _originalFsql.Delete<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => Delete<T1>().WhereDynamic(dywhere);
 | 
					        public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => Delete<T1>().WhereDynamic(dywhere);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IUpdate<T1> Update<T1>() where T1 : class
 | 
					        public IUpdate<T1> Update<T1>() where T1 : class
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var db = _resolveDbContext();
 | 
					            var db = _resolveDbContext?.Invoke();
 | 
				
			||||||
            db?.FlushCommand();
 | 
					            db?.FlushCommand();
 | 
				
			||||||
            var update = _originalFsql.Update<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
 | 
					            var update = _originalFsql.Update<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
 | 
				
			||||||
            if (db?.Options.NoneParameter != null) update.NoneParameter(db.Options.NoneParameter.Value);
 | 
					            if (db?.Options.NoneParameter != null) update.NoneParameter(db.Options.NoneParameter.Value);
 | 
				
			||||||
@@ -59,7 +59,7 @@ namespace FreeSql
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public IInsert<T1> Insert<T1>() where T1 : class
 | 
					        public IInsert<T1> Insert<T1>() where T1 : class
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var db = _resolveDbContext();
 | 
					            var db = _resolveDbContext?.Invoke();
 | 
				
			||||||
            db?.FlushCommand();
 | 
					            db?.FlushCommand();
 | 
				
			||||||
            var insert = _originalFsql.Insert<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
 | 
					            var insert = _originalFsql.Insert<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
 | 
				
			||||||
            if (db?.Options.NoneParameter != null) insert.NoneParameter(db.Options.NoneParameter.Value);
 | 
					            if (db?.Options.NoneParameter != null) insert.NoneParameter(db.Options.NoneParameter.Value);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
 | 
					    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
 | 
				
			||||||
    <Authors>YeXiangQin</Authors>
 | 
					    <Authors>YeXiangQin</Authors>
 | 
				
			||||||
    <Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Odbc, 达梦, And Access</Description>
 | 
					    <Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Odbc, 达梦, And Access</Description>
 | 
				
			||||||
    <PackageProjectUrl>https://github.com/2881099/FreeSql.DbContext</PackageProjectUrl>
 | 
					    <PackageProjectUrl>https://github.com/2881099/FreeSql/wiki/DbContext</PackageProjectUrl>
 | 
				
			||||||
    <PackageTags>FreeSql ORM DbContext</PackageTags>
 | 
					    <PackageTags>FreeSql ORM DbContext</PackageTags>
 | 
				
			||||||
    <RepositoryType>git</RepositoryType>
 | 
					    <RepositoryType>git</RepositoryType>
 | 
				
			||||||
    <PackageLicenseExpression>MIT</PackageLicenseExpression>
 | 
					    <PackageLicenseExpression>MIT</PackageLicenseExpression>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -227,41 +227,6 @@
 | 
				
			|||||||
            <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
 | 
					            <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
 | 
				
			||||||
            <returns></returns>
 | 
					            <returns></returns>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
        <member name="T:FreeSql.RepositoryUnitOfWorkManager">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            仓储的工作单元管理器
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="F:FreeSql.RepositoryUnitOfWorkManager.Propagation.Requierd">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="F:FreeSql.RepositoryUnitOfWorkManager.Propagation.Supports">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            支持当前事务,如果没有当前事务,就以非事务方法执行。
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="F:FreeSql.RepositoryUnitOfWorkManager.Propagation.Mandatory">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            使用当前事务,如果没有当前事务,就抛出异常。
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="F:FreeSql.RepositoryUnitOfWorkManager.Propagation.NotSupported">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="F:FreeSql.RepositoryUnitOfWorkManager.Propagation.Never">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            以非事务方式执行操作,如果当前事务存在则抛出异常。
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="F:FreeSql.RepositoryUnitOfWorkManager.Propagation.Nested">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IDataFilter`1.Enable(System.String[])">
 | 
					        <member name="M:FreeSql.IDataFilter`1.Enable(System.String[])">
 | 
				
			||||||
            <summary>
 | 
					            <summary>
 | 
				
			||||||
            开启过滤器,若使用 using 则使用完后,恢复为原有状态
 | 
					            开启过滤器,若使用 using 则使用完后,恢复为原有状态
 | 
				
			||||||
@@ -381,6 +346,65 @@
 | 
				
			|||||||
            例如:20191121_214504_1
 | 
					            例如:20191121_214504_1
 | 
				
			||||||
            </summary>
 | 
					            </summary>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="T:FreeSql.UnitOfWorkManager">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            工作单元管理器
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="P:FreeSql.UnitOfWorkManager.Current">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            当前的工作单元
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.UnitOfWorkManager.Binding(FreeSql.IBaseRepository)">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            将仓储的事务交给我管理
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="repository"></param>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.UnitOfWorkManager.Begin(FreeSql.Propagation,System.Nullable{System.Data.IsolationLevel})">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            创建工作单元
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="propagation">事务传播方式</param>
 | 
				
			||||||
 | 
					            <param name="isolationLevel">事务隔离级别</param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="T:FreeSql.Propagation">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            事务传播方式
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="F:FreeSql.Propagation.Requierd">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="F:FreeSql.Propagation.Supports">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            支持当前事务,如果没有当前事务,就以非事务方法执行。
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="F:FreeSql.Propagation.Mandatory">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            使用当前事务,如果没有当前事务,就抛出异常。
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="F:FreeSql.Propagation.NotSupported">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="F:FreeSql.Propagation.Never">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            以非事务方式执行操作,如果当前事务存在则抛出异常。
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="F:FreeSql.Propagation.Nested">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            以嵌套事务方式执行。
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
        <member name="M:FreeSqlDbContextExtensions.Entity``1(FreeSql.ICodeFirst,System.Action{FreeSql.Extensions.EfCoreFluentApi.EfCoreTableFluent{``0}})">
 | 
					        <member name="M:FreeSqlDbContextExtensions.Entity``1(FreeSql.ICodeFirst,System.Action{FreeSql.Extensions.EfCoreFluentApi.EfCoreTableFluent{``0}})">
 | 
				
			||||||
            <summary>
 | 
					            <summary>
 | 
				
			||||||
            EFCore 95% 相似的 FluentApi 扩展方法
 | 
					            EFCore 95% 相似的 FluentApi 扩展方法
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,201 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Data;
 | 
					 | 
				
			||||||
using System.Data.Common;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Linq.Expressions;
 | 
					 | 
				
			||||||
using System.Threading;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace FreeSql
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// 仓储的工作单元管理器
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public class RepositoryUnitOfWorkManager : IDisposable
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        IFreeSql _fsql;
 | 
					 | 
				
			||||||
        List<IRepositoryUnitOfWork> _uows = new List<IRepositoryUnitOfWork>();
 | 
					 | 
				
			||||||
        bool _isNotSupported = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public RepositoryUnitOfWorkManager(IFreeSql fsql)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            _fsql = fsql ?? throw new ArgumentNullException($"{nameof(RepositoryUnitOfWorkManager)} 构造参数 {nameof(fsql)} 不能为 null");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ~RepositoryUnitOfWorkManager() => this.Dispose();
 | 
					 | 
				
			||||||
        int _disposeCounter;
 | 
					 | 
				
			||||||
        public void Dispose()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (Interlocked.Increment(ref _disposeCounter) != 1) return;
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Exception exception = null;
 | 
					 | 
				
			||||||
                for (var a = _uows.Count - 1; a >= 0; a--)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    try
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        if (exception == null) _uows[a].Commit();
 | 
					 | 
				
			||||||
                        else _uows[a].Rollback();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    catch (Exception ex)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        if (exception == null) exception = ex;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if (exception != null) throw exception;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            finally
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                _uows.Clear();
 | 
					 | 
				
			||||||
                GC.SuppressFinalize(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public enum Propagation
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            /// <summary>
 | 
					 | 
				
			||||||
            /// 如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。
 | 
					 | 
				
			||||||
            /// </summary>
 | 
					 | 
				
			||||||
            Requierd,
 | 
					 | 
				
			||||||
            /// <summary>
 | 
					 | 
				
			||||||
            /// 支持当前事务,如果没有当前事务,就以非事务方法执行。
 | 
					 | 
				
			||||||
            /// </summary>
 | 
					 | 
				
			||||||
            Supports,
 | 
					 | 
				
			||||||
            /// <summary>
 | 
					 | 
				
			||||||
            /// 使用当前事务,如果没有当前事务,就抛出异常。
 | 
					 | 
				
			||||||
            /// </summary>
 | 
					 | 
				
			||||||
            Mandatory,
 | 
					 | 
				
			||||||
            /// <summary>
 | 
					 | 
				
			||||||
            /// 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 | 
					 | 
				
			||||||
            /// </summary>
 | 
					 | 
				
			||||||
            NotSupported,
 | 
					 | 
				
			||||||
            /// <summary>
 | 
					 | 
				
			||||||
            /// 以非事务方式执行操作,如果当前事务存在则抛出异常。
 | 
					 | 
				
			||||||
            /// </summary>
 | 
					 | 
				
			||||||
            Never,
 | 
					 | 
				
			||||||
            /// <summary>
 | 
					 | 
				
			||||||
            /// 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。
 | 
					 | 
				
			||||||
            /// </summary>
 | 
					 | 
				
			||||||
            Nested
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public IRepositoryUnitOfWork Begin(Propagation propagation, IsolationLevel? isolationLevel = null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (propagation == Propagation.Requierd)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (_isNotSupported == false)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    for (var a = _uows.Count - 1; a >= 0; a--)
 | 
					 | 
				
			||||||
                        if (_uows[a].GetOrBeginTransaction(false) != null)
 | 
					 | 
				
			||||||
                            return new UnitOfWorkProxy(_uows[a]);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                var uow = new RepositoryUnitOfWork(_fsql);
 | 
					 | 
				
			||||||
                if (isolationLevel != null) uow.IsolationLevel = isolationLevel.Value;
 | 
					 | 
				
			||||||
                try { uow.GetOrBeginTransaction(); }
 | 
					 | 
				
			||||||
                catch { uow.Dispose(); throw; }
 | 
					 | 
				
			||||||
                _uows.Add(uow);
 | 
					 | 
				
			||||||
                return uow;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (propagation == Propagation.Supports)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (_isNotSupported == false)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    for (var a = _uows.Count - 1; a >= 0; a--)
 | 
					 | 
				
			||||||
                        if (_uows[a].GetOrBeginTransaction(false) != null)
 | 
					 | 
				
			||||||
                            return new UnitOfWorkProxy(_uows[a]);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return new UnitOfWorkNothing(_fsql);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (propagation == Propagation.Mandatory)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (_isNotSupported == false)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    for (var a = _uows.Count - 1; a >= 0; a--)
 | 
					 | 
				
			||||||
                        if (_uows[a].GetOrBeginTransaction(false) != null)
 | 
					 | 
				
			||||||
                            return new UnitOfWorkProxy(_uows[a]);
 | 
					 | 
				
			||||||
                    throw new Exception("Propagation_Mandatory: 使用当前事务,如果没有当前事务,就抛出异常");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                throw new Exception("Propagation_Mandatory: 使用当前事务,如果没有当前事务,就抛出异常(NotSupported 事务挂起中)");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (propagation == Propagation.NotSupported)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (_isNotSupported == false)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    _isNotSupported = true;
 | 
					 | 
				
			||||||
                    return new UnitOfWorkNothing(_fsql) { OnDispose = () => _isNotSupported = false };
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return new UnitOfWorkNothing(_fsql);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (propagation == Propagation.Never)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (_isNotSupported == false)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    for (var a = _uows.Count - 1; a >= 0; a--)
 | 
					 | 
				
			||||||
                        if (_uows[a].GetOrBeginTransaction(false) != null)
 | 
					 | 
				
			||||||
                            throw new Exception("Propagation_Never: 以非事务方式执行操作,如果当前事务存在则抛出异常");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return new UnitOfWorkNothing(_fsql);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (propagation == Propagation.Nested)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                var uow = new RepositoryUnitOfWork(_fsql);
 | 
					 | 
				
			||||||
                if (isolationLevel != null) uow.IsolationLevel = isolationLevel.Value;
 | 
					 | 
				
			||||||
                try { uow.GetOrBeginTransaction(); }
 | 
					 | 
				
			||||||
                catch { uow.Dispose(); throw; }
 | 
					 | 
				
			||||||
                _uows.Add(uow);
 | 
					 | 
				
			||||||
                return uow;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            throw new NotImplementedException();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        class UnitOfWorkProxy : IRepositoryUnitOfWork
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            IRepositoryUnitOfWork _baseUow;
 | 
					 | 
				
			||||||
            public UnitOfWorkProxy(IRepositoryUnitOfWork baseUow) => _baseUow = baseUow;
 | 
					 | 
				
			||||||
            public IsolationLevel? IsolationLevel { get => _baseUow.IsolationLevel; set { } }
 | 
					 | 
				
			||||||
            public DbContext.EntityChangeReport EntityChangeReport => _baseUow.EntityChangeReport;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            public bool Enable => _baseUow.Enable;
 | 
					 | 
				
			||||||
            public void Close() => _baseUow.Close();
 | 
					 | 
				
			||||||
            public void Open() => _baseUow.Open();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => _baseUow.GetOrBeginTransaction(isCreate);
 | 
					 | 
				
			||||||
            public void Commit() => this.Dispose();
 | 
					 | 
				
			||||||
            public void Rollback() => _baseUow.Rollback();
 | 
					 | 
				
			||||||
            public void Dispose() { }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            public IBaseRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class => _baseUow.GetRepository<TEntity, TKey>(filter);
 | 
					 | 
				
			||||||
            public IBaseRepository<TEntity> GetRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class => _baseUow.GetRepository<TEntity>(filter);
 | 
					 | 
				
			||||||
            public IBaseRepository<TEntity, Guid> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class => _baseUow.GetGuidRepository<TEntity>(filter);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        class UnitOfWorkNothing : IRepositoryUnitOfWork
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            internal IFreeSql _fsql;
 | 
					 | 
				
			||||||
            internal Action OnDispose;
 | 
					 | 
				
			||||||
            public UnitOfWorkNothing(IFreeSql fsql) => _fsql = fsql;
 | 
					 | 
				
			||||||
            public IsolationLevel? IsolationLevel { get; set; }
 | 
					 | 
				
			||||||
            public DbContext.EntityChangeReport EntityChangeReport { get; } = new DbContext.EntityChangeReport();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            public bool Enable { get; }
 | 
					 | 
				
			||||||
            public void Close() { }
 | 
					 | 
				
			||||||
            public void Open() { }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => null;
 | 
					 | 
				
			||||||
            public void Commit()
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (EntityChangeReport != null && EntityChangeReport.OnChange != null && EntityChangeReport.Report.Any() == true)
 | 
					 | 
				
			||||||
                    EntityChangeReport.OnChange.Invoke(EntityChangeReport.Report);
 | 
					 | 
				
			||||||
                this.Dispose();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            public void Rollback() => this.Dispose();
 | 
					 | 
				
			||||||
            public void Dispose() {
 | 
					 | 
				
			||||||
                EntityChangeReport?.Report.Clear();
 | 
					 | 
				
			||||||
                OnDispose?.Invoke();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            public IBaseRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class => new DefaultRepository<TEntity, TKey>(_fsql, filter);
 | 
					 | 
				
			||||||
            public IBaseRepository<TEntity> GetRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class => new DefaultRepository<TEntity,  int>(_fsql, filter);
 | 
					 | 
				
			||||||
            public IBaseRepository<TEntity, Guid> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class => new GuidRepository<TEntity>(_fsql, filter, asTable);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -7,11 +7,19 @@ namespace FreeSql
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        public DefaultRepository(IFreeSql fsql) : base(fsql, null, null) { }
 | 
					        public DefaultRepository(IFreeSql fsql) : base(fsql, null, null) { }
 | 
				
			||||||
        public DefaultRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter) : base(fsql, filter, null) { }
 | 
					        public DefaultRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter) : base(fsql, filter, null) { }
 | 
				
			||||||
 | 
					        public DefaultRepository(IFreeSql fsql, UnitOfWorkManager uowManger) : base(uowManger?.Orm ?? fsql, null, null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            uowManger?.Binding(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class GuidRepository<TEntity> : BaseRepository<TEntity, Guid> where TEntity : class
 | 
					    public class GuidRepository<TEntity> : BaseRepository<TEntity, Guid> where TEntity : class
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public GuidRepository(IFreeSql fsql) : this(fsql, null, null) { }
 | 
					        public GuidRepository(IFreeSql fsql) : this(fsql, null, null) { }
 | 
				
			||||||
        public GuidRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable) : base(fsql, filter, asTable) { }
 | 
					        public GuidRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable) : base(fsql, filter, asTable) { }
 | 
				
			||||||
 | 
					        public GuidRepository(IFreeSql fsql, UnitOfWorkManager uowManger) : base(uowManger?.Orm ?? fsql, null, null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            uowManger?.Binding(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										274
									
								
								FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,274 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Data;
 | 
				
			||||||
 | 
					using System.Data.Common;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace FreeSql
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 工作单元管理器
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public class UnitOfWorkManager : IDisposable
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DbContextScopedFreeSql _ormScoped;
 | 
				
			||||||
 | 
					        public IFreeSql Orm => _ormScoped;
 | 
				
			||||||
 | 
					        List<UowInfo> _rawUows = new List<UowInfo>();
 | 
				
			||||||
 | 
					        List<UowInfo> _allUows = new List<UowInfo>();
 | 
				
			||||||
 | 
					        List<RepoInfo> _repos = new List<RepoInfo>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public UnitOfWorkManager(IFreeSql fsql)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (fsql == null) throw new ArgumentNullException($"{nameof(UnitOfWorkManager)} 构造参数 {nameof(fsql)} 不能为 null");
 | 
				
			||||||
 | 
					            _ormScoped = DbContextScopedFreeSql.Create(fsql, null, () => this.Current);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Dispose
 | 
				
			||||||
 | 
					        ~UnitOfWorkManager() => this.Dispose();
 | 
				
			||||||
 | 
					        int _disposeCounter;
 | 
				
			||||||
 | 
					        public void Dispose()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (Interlocked.Increment(ref _disposeCounter) != 1) return;
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Exception exception = null;
 | 
				
			||||||
 | 
					                for (var a = _rawUows.Count - 1; a >= 0; a--)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    try
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if (exception == null) _rawUows[a].Uow.Commit();
 | 
				
			||||||
 | 
					                        else _rawUows[a].Uow.Rollback();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    catch (Exception ex)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if (exception == null) exception = ex;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (exception != null) throw exception;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            finally
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _rawUows.Clear();
 | 
				
			||||||
 | 
					                _allUows.Clear();
 | 
				
			||||||
 | 
					                _repos.Clear();
 | 
				
			||||||
 | 
					                GC.SuppressFinalize(this);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 当前的工作单元
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public IUnitOfWork Current => _allUows.LastOrDefault()?.Uow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 将仓储的事务交给我管理
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="repository"></param>
 | 
				
			||||||
 | 
					        public void Binding(IBaseRepository repository)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var repoInfo = new RepoInfo(repository);
 | 
				
			||||||
 | 
					            repository.UnitOfWork = Current;
 | 
				
			||||||
 | 
					            _repos.Add(repoInfo);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        void SetAllRepositoryUow()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            foreach (var repo in _repos)
 | 
				
			||||||
 | 
					                repo.Repository.UnitOfWork = Current ?? repo.OrginalUow;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 创建工作单元
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="propagation">事务传播方式</param>
 | 
				
			||||||
 | 
					        /// <param name="isolationLevel">事务隔离级别</param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public IUnitOfWork Begin(Propagation propagation = Propagation.Requierd, IsolationLevel? isolationLevel = null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            switch (propagation)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case Propagation.Requierd: return FindedUowCreateVirtual() ?? CreateUow(isolationLevel);
 | 
				
			||||||
 | 
					                case Propagation.Supports: return FindedUowCreateVirtual() ?? CreateUowNothing(_allUows.LastOrDefault()?.IsNotSupported ?? false);
 | 
				
			||||||
 | 
					                case Propagation.Mandatory: return FindedUowCreateVirtual() ?? throw new Exception("Propagation_Mandatory: 使用当前事务,如果没有当前事务,就抛出异常");
 | 
				
			||||||
 | 
					                case Propagation.NotSupported: return CreateUowNothing(true);
 | 
				
			||||||
 | 
					                case Propagation.Never:
 | 
				
			||||||
 | 
					                    var isNotSupported = _allUows.LastOrDefault()?.IsNotSupported ?? false;
 | 
				
			||||||
 | 
					                    if (isNotSupported == false)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        for (var a = _rawUows.Count - 1; a >= 0; a--)
 | 
				
			||||||
 | 
					                            if (_rawUows[a].Uow.GetOrBeginTransaction(false) != null)
 | 
				
			||||||
 | 
					                                throw new Exception("Propagation_Never: 以非事务方式执行操作,如果当前事务存在则抛出异常");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return CreateUowNothing(isNotSupported);
 | 
				
			||||||
 | 
					                case Propagation.Nested: return CreateUow(isolationLevel);
 | 
				
			||||||
 | 
					                default: throw new NotImplementedException();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IUnitOfWork FindedUowCreateVirtual()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var isNotSupported = _allUows.LastOrDefault()?.IsNotSupported ?? false;
 | 
				
			||||||
 | 
					            if (isNotSupported == false)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                for (var a = _rawUows.Count - 1; a >= 0; a--)
 | 
				
			||||||
 | 
					                    if (_rawUows[a].Uow.GetOrBeginTransaction(false) != null)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        var uow = new UnitOfWorkVirtual(_rawUows[a].Uow);
 | 
				
			||||||
 | 
					                        var uowInfo = new UowInfo(uow, UowInfo.UowType.Virtual, isNotSupported);
 | 
				
			||||||
 | 
					                        uow.OnDispose = () => _allUows.Remove(uowInfo);
 | 
				
			||||||
 | 
					                        _allUows.Add(uowInfo);
 | 
				
			||||||
 | 
					                        SetAllRepositoryUow();
 | 
				
			||||||
 | 
					                        return uow;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        IUnitOfWork CreateUowNothing(bool isNotSupported)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var uow = new UnitOfWorkNothing(Orm);
 | 
				
			||||||
 | 
					            var uowInfo = new UowInfo(uow, UowInfo.UowType.Nothing, isNotSupported);
 | 
				
			||||||
 | 
					            uow.OnDispose = () => _allUows.Remove(uowInfo);
 | 
				
			||||||
 | 
					            _allUows.Add(uowInfo);
 | 
				
			||||||
 | 
					            SetAllRepositoryUow();
 | 
				
			||||||
 | 
					            return uow;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        IUnitOfWork CreateUow(IsolationLevel? isolationLevel)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var uow = new UnitOfWorkOrginal(new UnitOfWork(Orm));
 | 
				
			||||||
 | 
					            var uowInfo = new UowInfo(uow, UowInfo.UowType.Orginal, false);
 | 
				
			||||||
 | 
					            if (isolationLevel != null) uow.IsolationLevel = isolationLevel.Value;
 | 
				
			||||||
 | 
					            try { uow.GetOrBeginTransaction(); }
 | 
				
			||||||
 | 
					            catch { uow.Dispose(); throw; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uow.OnDispose = () =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _rawUows.Remove(uowInfo);
 | 
				
			||||||
 | 
					                _allUows.Remove(uowInfo);
 | 
				
			||||||
 | 
					                SetAllRepositoryUow();
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            _rawUows.Add(uowInfo);
 | 
				
			||||||
 | 
					            _allUows.Add(uowInfo);
 | 
				
			||||||
 | 
					            SetAllRepositoryUow();
 | 
				
			||||||
 | 
					            return uow;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class RepoInfo
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public IBaseRepository Repository;
 | 
				
			||||||
 | 
					            public IUnitOfWork OrginalUow;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            public RepoInfo(IBaseRepository repository)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.Repository = repository;
 | 
				
			||||||
 | 
					                this.OrginalUow = repository.UnitOfWork;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        class UowInfo
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public IUnitOfWork Uow;
 | 
				
			||||||
 | 
					            public UowType Type;
 | 
				
			||||||
 | 
					            public bool IsNotSupported;
 | 
				
			||||||
 | 
					            public enum UowType { Orginal, Virtual, Nothing }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public UowInfo(IUnitOfWork uow, UowType type, bool isNotSupported)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.Uow = uow;
 | 
				
			||||||
 | 
					                this.Type = type;
 | 
				
			||||||
 | 
					                this.IsNotSupported = isNotSupported;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        class UnitOfWorkOrginal : IUnitOfWork
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            IUnitOfWork _baseUow;
 | 
				
			||||||
 | 
					            internal Action OnDispose;
 | 
				
			||||||
 | 
					            public UnitOfWorkOrginal(IUnitOfWork baseUow) => _baseUow = baseUow;
 | 
				
			||||||
 | 
					            public IsolationLevel? IsolationLevel { get => _baseUow.IsolationLevel; set => _baseUow.IsolationLevel = value; }
 | 
				
			||||||
 | 
					            public DbContext.EntityChangeReport EntityChangeReport => _baseUow.EntityChangeReport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public bool Enable => _baseUow.Enable;
 | 
				
			||||||
 | 
					            public void Close() => _baseUow.Close();
 | 
				
			||||||
 | 
					            public void Open() => _baseUow.Open();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => _baseUow.GetOrBeginTransaction(isCreate);
 | 
				
			||||||
 | 
					            public void Commit() => _baseUow.Commit();
 | 
				
			||||||
 | 
					            public void Rollback() => _baseUow.Rollback();
 | 
				
			||||||
 | 
					            public void Dispose()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _baseUow.Dispose();
 | 
				
			||||||
 | 
					                OnDispose?.Invoke();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        class UnitOfWorkVirtual : IUnitOfWork
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            IUnitOfWork _baseUow;
 | 
				
			||||||
 | 
					            internal Action OnDispose;
 | 
				
			||||||
 | 
					            public UnitOfWorkVirtual(IUnitOfWork baseUow) => _baseUow = baseUow;
 | 
				
			||||||
 | 
					            public IsolationLevel? IsolationLevel { get => _baseUow.IsolationLevel; set { } }
 | 
				
			||||||
 | 
					            public DbContext.EntityChangeReport EntityChangeReport => _baseUow.EntityChangeReport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public bool Enable => _baseUow.Enable;
 | 
				
			||||||
 | 
					            public void Close() => _baseUow.Close();
 | 
				
			||||||
 | 
					            public void Open() => _baseUow.Open();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => _baseUow.GetOrBeginTransaction(isCreate);
 | 
				
			||||||
 | 
					            public void Commit() { }
 | 
				
			||||||
 | 
					            public void Rollback() => _baseUow.Rollback();
 | 
				
			||||||
 | 
					            public void Dispose() => OnDispose?.Invoke();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        class UnitOfWorkNothing : IUnitOfWork
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            internal IFreeSql _fsql;
 | 
				
			||||||
 | 
					            internal Action OnDispose;
 | 
				
			||||||
 | 
					            public UnitOfWorkNothing(IFreeSql fsql) => _fsql = fsql;
 | 
				
			||||||
 | 
					            public IsolationLevel? IsolationLevel { get; set; }
 | 
				
			||||||
 | 
					            public DbContext.EntityChangeReport EntityChangeReport { get; } = new DbContext.EntityChangeReport();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public bool Enable { get; }
 | 
				
			||||||
 | 
					            public void Close() { }
 | 
				
			||||||
 | 
					            public void Open() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => null;
 | 
				
			||||||
 | 
					            public void Commit()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (EntityChangeReport != null && EntityChangeReport.OnChange != null && EntityChangeReport.Report.Any() == true)
 | 
				
			||||||
 | 
					                    EntityChangeReport.OnChange.Invoke(EntityChangeReport.Report);
 | 
				
			||||||
 | 
					                EntityChangeReport?.Report.Clear();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            public void Rollback() => EntityChangeReport?.Report.Clear();
 | 
				
			||||||
 | 
					            public void Dispose() => OnDispose?.Invoke();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 事务传播方式
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public enum Propagation
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        Requierd,
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 支持当前事务,如果没有当前事务,就以非事务方法执行。
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        Supports,
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 使用当前事务,如果没有当前事务,就抛出异常。
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        Mandatory,
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        NotSupported,
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 以非事务方式执行操作,如果当前事务存在则抛出异常。
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        Never,
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 以嵌套事务方式执行。
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        Nested
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								FreeSql.sln
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								FreeSql.sln
									
									
									
									
									
								
							@@ -78,6 +78,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.Linq", "
 | 
				
			|||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.Dameng", "Providers\FreeSql.Provider.Dameng\FreeSql.Provider.Dameng.csproj", "{E74D90E8-1CBC-4677-817B-1CA05AB97937}"
 | 
					Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.Dameng", "Providers\FreeSql.Provider.Dameng\FreeSql.Provider.Dameng.csproj", "{E74D90E8-1CBC-4677-817B-1CA05AB97937}"
 | 
				
			||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aspnetcore_transaction", "Examples\aspnetcore_transaction\aspnetcore_transaction.csproj", "{07AB0B37-A8B1-4FB1-9259-7B804E369E36}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
Global
 | 
					Global
 | 
				
			||||||
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
						GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
				
			||||||
		Debug|Any CPU = Debug|Any CPU
 | 
							Debug|Any CPU = Debug|Any CPU
 | 
				
			||||||
@@ -472,6 +474,18 @@ Global
 | 
				
			|||||||
		{E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x64.Build.0 = Release|Any CPU
 | 
							{E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x64.Build.0 = Release|Any CPU
 | 
				
			||||||
		{E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x86.ActiveCfg = Release|Any CPU
 | 
							{E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x86.ActiveCfg = Release|Any CPU
 | 
				
			||||||
		{E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x86.Build.0 = Release|Any CPU
 | 
							{E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x86.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Debug|x64.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Debug|x86.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Release|x64.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Release|x64.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Release|x86.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36}.Release|x86.Build.0 = Release|Any CPU
 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
	GlobalSection(SolutionProperties) = preSolution
 | 
						GlobalSection(SolutionProperties) = preSolution
 | 
				
			||||||
		HideSolutionNode = FALSE
 | 
							HideSolutionNode = FALSE
 | 
				
			||||||
@@ -499,6 +513,7 @@ Global
 | 
				
			|||||||
		{B397A761-F646-41CF-A160-AB6C05DAF2FB} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
 | 
							{B397A761-F646-41CF-A160-AB6C05DAF2FB} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
 | 
				
			||||||
		{57B3F5B0-D46A-4442-8EC6-9A9A784404B7} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
 | 
							{57B3F5B0-D46A-4442-8EC6-9A9A784404B7} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
 | 
				
			||||||
		{E74D90E8-1CBC-4677-817B-1CA05AB97937} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
 | 
							{E74D90E8-1CBC-4677-817B-1CA05AB97937} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
 | 
				
			||||||
 | 
							{07AB0B37-A8B1-4FB1-9259-7B804E369E36} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
	GlobalSection(ExtensibilityGlobals) = postSolution
 | 
						GlobalSection(ExtensibilityGlobals) = postSolution
 | 
				
			||||||
		SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98}
 | 
							SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2310,137 +2310,6 @@
 | 
				
			|||||||
            <param name="parms"></param>
 | 
					            <param name="parms"></param>
 | 
				
			||||||
            <returns></returns>
 | 
					            <returns></returns>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{System.Data.Common.DbDataReader,System.Threading.Tasks.Task},System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="readerHander"></param>
 | 
					 | 
				
			||||||
            <param name="cmdType"></param>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{System.Data.Common.DbDataReader,System.Threading.Tasks.Task},System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询,ExecuteReaderAsync(dr => {}, "select * from user where age > ?age", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询,ExecuteArrayAsync("select * from user where age > ?age", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询,ExecuteDataSetAsync("select * from user where age > ?age; select 2", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            查询,ExecuteDataTableAsync("select * from user where age > ?age", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            在【主库】执行
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdType"></param>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            在【主库】执行,ExecuteNonQueryAsync("delete from user where age > ?age", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            在【主库】执行
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdType"></param>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            在【主库】执行,ExecuteScalarAsync("select 1 from user where age > ?age", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.QueryAsync``1(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new SqlParameter { ParameterName = "age", Value = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <typeparam name="T"></typeparam>
 | 
					 | 
				
			||||||
            <param name="cmdType"></param>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.QueryAsync``1(System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <typeparam name="T"></typeparam>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.QueryAsync``2(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <typeparam name="T1"></typeparam>
 | 
					 | 
				
			||||||
            <param name="cmdType"></param>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="cmdParms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.IAdo.QueryAsync``2(System.String,System.Object)">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new { age = 25 })
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <typeparam name="T1"></typeparam>
 | 
					 | 
				
			||||||
            <param name="cmdText"></param>
 | 
					 | 
				
			||||||
            <param name="parms"></param>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="E:FreeSql.IAop.ParseExpression">
 | 
					        <member name="E:FreeSql.IAop.ParseExpression">
 | 
				
			||||||
            <summary>
 | 
					            <summary>
 | 
				
			||||||
            可自定义解析表达式
 | 
					            可自定义解析表达式
 | 
				
			||||||
@@ -2961,12 +2830,6 @@
 | 
				
			|||||||
            <param name="timeout">超时</param>
 | 
					            <param name="timeout">超时</param>
 | 
				
			||||||
            <returns></returns>
 | 
					            <returns></returns>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
        <member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.GetAsync">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            获取资源
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <returns></returns>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)">
 | 
					        <member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)">
 | 
				
			||||||
            <summary>
 | 
					            <summary>
 | 
				
			||||||
            使用完毕后,归还资源
 | 
					            使用完毕后,归还资源
 | 
				
			||||||
@@ -3037,12 +2900,6 @@
 | 
				
			|||||||
            </summary>
 | 
					            </summary>
 | 
				
			||||||
            <param name="obj">资源对象</param>
 | 
					            <param name="obj">资源对象</param>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
        <member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnGetAsync(FreeSql.Internal.ObjectPool.Object{`0})">
 | 
					 | 
				
			||||||
            <summary>
 | 
					 | 
				
			||||||
            从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
 | 
					 | 
				
			||||||
            </summary>
 | 
					 | 
				
			||||||
            <param name="obj">资源对象</param>
 | 
					 | 
				
			||||||
        </member>
 | 
					 | 
				
			||||||
        <member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})">
 | 
					        <member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})">
 | 
				
			||||||
            <summary>
 | 
					            <summary>
 | 
				
			||||||
            归还对象给对象池的时候触发
 | 
					            归还对象给对象池的时候触发
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,14 +16,14 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
        class Transaction2
 | 
					        class Transaction2
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            internal Aop.TraceBeforeEventArgs AopBefore;
 | 
					            internal Aop.TraceBeforeEventArgs AopBefore;
 | 
				
			||||||
            internal Object<DbConnection> Conn;
 | 
					            internal Object<DbConnection> Connection;
 | 
				
			||||||
            internal DbTransaction Transaction;
 | 
					            internal DbTransaction Transaction;
 | 
				
			||||||
            internal DateTime RunTime;
 | 
					            internal DateTime RunTime;
 | 
				
			||||||
            internal TimeSpan Timeout;
 | 
					            internal TimeSpan Timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            public Transaction2(Object<DbConnection> conn, DbTransaction tran, TimeSpan timeout)
 | 
					            public Transaction2(Object<DbConnection> conn, DbTransaction tran, TimeSpan timeout)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Conn = conn;
 | 
					                Connection = conn;
 | 
				
			||||||
                Transaction = tran;
 | 
					                Transaction = tran;
 | 
				
			||||||
                RunTime = DateTime.Now;
 | 
					                RunTime = DateTime.Now;
 | 
				
			||||||
                Timeout = timeout;
 | 
					                Timeout = timeout;
 | 
				
			||||||
@@ -31,7 +31,6 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private ConcurrentDictionary<int, Transaction2> _trans = new ConcurrentDictionary<int, Transaction2>();
 | 
					        private ConcurrentDictionary<int, Transaction2> _trans = new ConcurrentDictionary<int, Transaction2>();
 | 
				
			||||||
        private object _trans_lock = new object();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DbTransaction TransactionCurrentThread => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.Transaction : null;
 | 
					        public DbTransaction TransactionCurrentThread => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.Transaction : null;
 | 
				
			||||||
        public Aop.TraceBeforeEventArgs TransactionCurrentThreadAopBefore => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.AopBefore : null;
 | 
					        public Aop.TraceBeforeEventArgs TransactionCurrentThreadAopBefore => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.AopBefore : null;
 | 
				
			||||||
@@ -61,8 +60,6 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
                throw ex;
 | 
					                throw ex;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (_trans.ContainsKey(tid)) CommitTransaction();
 | 
					            if (_trans.ContainsKey(tid)) CommitTransaction();
 | 
				
			||||||
 | 
					 | 
				
			||||||
            lock (_trans_lock)
 | 
					 | 
				
			||||||
            _trans.TryAdd(tid, tran);
 | 
					            _trans.TryAdd(tid, tran);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -70,26 +67,20 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (_trans.Count > 0)
 | 
					            if (_trans.Count > 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Transaction2[] trans = null;
 | 
					                var trans = _trans.Values.Where(st2 => DateTime.Now.Subtract(st2.RunTime) > st2.Timeout).ToArray();
 | 
				
			||||||
                lock (_trans_lock)
 | 
					                foreach (var tran in trans) CommitTransaction(true, tran, null, "Timeout自动提交");
 | 
				
			||||||
                    trans = _trans.Values.Where(st2 => DateTime.Now.Subtract(st2.RunTime) > st2.Timeout).ToArray();
 | 
					 | 
				
			||||||
                foreach (Transaction2 tran in trans) CommitTransaction(true, tran, null, "Timeout自动提交");
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        private void CommitTransaction(bool isCommit, Transaction2 tran, Exception rollbackException, string remark = null)
 | 
					        private void CommitTransaction(bool isCommit, Transaction2 tran, Exception rollbackException, string remark = null)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (tran == null || tran.Transaction == null || tran.Transaction.Connection == null) return;
 | 
					            if (tran == null || tran.Transaction == null || tran.Transaction.Connection == null) return;
 | 
				
			||||||
 | 
					            _trans.TryRemove(tran.Connection.LastGetThreadId, out var oldtran);
 | 
				
			||||||
            if (_trans.ContainsKey(tran.Conn.LastGetThreadId))
 | 
					 | 
				
			||||||
                lock (_trans_lock)
 | 
					 | 
				
			||||||
                    if (_trans.ContainsKey(tran.Conn.LastGetThreadId))
 | 
					 | 
				
			||||||
                        _trans.TryRemove(tran.Conn.LastGetThreadId, out var oldtran);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Exception ex = null;
 | 
					            Exception ex = null;
 | 
				
			||||||
            if (string.IsNullOrEmpty(remark)) remark = isCommit ? "提交" : "回滚";
 | 
					            if (string.IsNullOrEmpty(remark)) remark = isCommit ? "提交" : "回滚";
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Trace.WriteLine($"线程{tran.Conn.LastGetThreadId}事务{remark}");
 | 
					                Trace.WriteLine($"线程{tran.Connection.LastGetThreadId}事务{remark}");
 | 
				
			||||||
                if (isCommit) tran.Transaction.Commit();
 | 
					                if (isCommit) tran.Transaction.Commit();
 | 
				
			||||||
                else tran.Transaction.Rollback();
 | 
					                else tran.Transaction.Rollback();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -100,7 +91,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            finally
 | 
					            finally
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ReturnConnection(MasterPool, tran.Conn, ex); //MasterPool.Return(tran.Conn, ex);
 | 
					                ReturnConnection(MasterPool, tran.Connection, ex); //MasterPool.Return(tran.Conn, ex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var after = new Aop.TraceAfterEventArgs(tran.AopBefore, remark, ex ?? rollbackException);
 | 
					                var after = new Aop.TraceAfterEventArgs(tran.AopBefore, remark, ex ?? rollbackException);
 | 
				
			||||||
                _util?._orm?.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
					                _util?._orm?.Aop.TraceAfterHandler?.Invoke(this, after);
 | 
				
			||||||
@@ -141,10 +132,8 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
            if (Interlocked.Increment(ref _disposeCounter) != 1) return;
 | 
					            if (Interlocked.Increment(ref _disposeCounter) != 1) return;
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Transaction2[] trans = null;
 | 
					                var trans = _trans.Values.ToArray();
 | 
				
			||||||
                lock (_trans_lock)
 | 
					                foreach (var tran in trans) CommitTransaction(false, tran, null, "Dispose自动提交");
 | 
				
			||||||
                    trans = _trans.Values.ToArray();
 | 
					 | 
				
			||||||
                foreach (Transaction2 tran in trans) CommitTransaction(false, tran, null, "Dispose自动提交");
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch { }
 | 
					            catch { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user