mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	- 增加 Where In 表达式解析;
- 增加 FreeSqlBuilder.UseConnectionFactory 自定义数据库连接对象的创建方法;
This commit is contained in:
		@@ -660,6 +660,7 @@ namespace FreeSql.Internal
 | 
			
		||||
                            case "Min":
 | 
			
		||||
                            case "Max":
 | 
			
		||||
                            case "Avg":
 | 
			
		||||
                            case "ToList": //where in
 | 
			
		||||
                            case "First":
 | 
			
		||||
                                var anyArgs = exp3.Arguments;
 | 
			
		||||
                                var exp3Stack = new Stack<Expression>();
 | 
			
		||||
@@ -732,7 +733,8 @@ namespace FreeSql.Internal
 | 
			
		||||
                                        if (fsql == null) fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke();
 | 
			
		||||
                                        fsqlType = fsql?.GetType();
 | 
			
		||||
                                        if (fsqlType == null) break;
 | 
			
		||||
                                        fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1);
 | 
			
		||||
                                        if (exp3.Method.Name != "ToList")
 | 
			
		||||
                                            fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1);
 | 
			
		||||
                                        fsqltables = fsqlType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(fsql) as List<SelectTableInfo>;
 | 
			
		||||
                                        //fsqltables[0].Alias = $"{tsc._tables[0].Alias}_{fsqltables[0].Alias}";
 | 
			
		||||
                                        if (fsqltables != tsc._tables)
 | 
			
		||||
@@ -915,6 +917,7 @@ namespace FreeSql.Internal
 | 
			
		||||
                                            if (string.IsNullOrEmpty(sqlSum) == false)
 | 
			
		||||
                                                return $"({sqlSum.Replace("\r\n", "\r\n\t")})";
 | 
			
		||||
                                            break;
 | 
			
		||||
                                        case "ToList":
 | 
			
		||||
                                        case "First":
 | 
			
		||||
                                            var tscClone2 = tsc.CloneDisableDiyParse();
 | 
			
		||||
                                            tscClone2.isDisableDiyParse = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
    public abstract partial class AdoProvider : IAdo, IDisposable
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        protected abstract void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex);
 | 
			
		||||
        protected abstract void ReturnConnection(IObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex);
 | 
			
		||||
        protected abstract DbCommand CreateCommand();
 | 
			
		||||
        protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
 | 
			
		||||
        public Action<DbCommand> AopCommandExecuting { get; set; }
 | 
			
		||||
@@ -22,8 +22,8 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
 | 
			
		||||
        protected bool IsTracePerformance => AopCommandExecuted != null;
 | 
			
		||||
 | 
			
		||||
        public ObjectPool<DbConnection> MasterPool { get; protected set; }
 | 
			
		||||
        public List<ObjectPool<DbConnection>> SlavePools { get; } = new List<ObjectPool<DbConnection>>();
 | 
			
		||||
        public IObjectPool<DbConnection> MasterPool { get; protected set; }
 | 
			
		||||
        public List<IObjectPool<DbConnection>> SlavePools { get; } = new List<IObjectPool<DbConnection>>();
 | 
			
		||||
        public DataType DataType { get; }
 | 
			
		||||
        protected CommonUtils _util { get; set; }
 | 
			
		||||
        protected int slaveUnavailables = 0;
 | 
			
		||||
@@ -35,7 +35,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            this.DataType = dataType;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void LoggerException(ObjectPool<DbConnection> pool, (DbCommand cmd, bool isclose) pc, Exception e, DateTime dt, StringBuilder logtxt, bool isThrowException = true)
 | 
			
		||||
        void LoggerException(IObjectPool<DbConnection> pool, (DbCommand cmd, bool isclose) pc, Exception e, DateTime dt, StringBuilder logtxt, bool isThrowException = true)
 | 
			
		||||
        {
 | 
			
		||||
            var cmd = pc.cmd;
 | 
			
		||||
            if (pc.isclose) pc.cmd.Connection.Close();
 | 
			
		||||
@@ -76,7 +76,11 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            AopCommandExecuted?.Invoke(cmd, log.ToString());
 | 
			
		||||
 | 
			
		||||
            cmd.Parameters.Clear();
 | 
			
		||||
            if (isThrowException) throw e;
 | 
			
		||||
            if (isThrowException)
 | 
			
		||||
            {
 | 
			
		||||
                cmd.Dispose();
 | 
			
		||||
                throw e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal Dictionary<string, PropertyInfo> GetQueryTypeProperties(Type type)
 | 
			
		||||
@@ -515,7 +519,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        //查从库
 | 
			
		||||
                        this.SlavePools : (
 | 
			
		||||
                        //查主库
 | 
			
		||||
                        slaveUnavailables == this.SlavePools.Count ? new List<ObjectPool<DbConnection>>() :
 | 
			
		||||
                        slaveUnavailables == this.SlavePools.Count ? new List<IObjectPool<DbConnection>>() :
 | 
			
		||||
                        //查从库可用
 | 
			
		||||
                        this.SlavePools.Where(sp => sp.IsAvailable).ToList());
 | 
			
		||||
                    if (availables.Any())
 | 
			
		||||
@@ -556,6 +560,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        }
 | 
			
		||||
                        LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
 | 
			
		||||
                        pc.cmd.Parameters.Clear();
 | 
			
		||||
                        pc.cmd.Dispose();
 | 
			
		||||
                        ExecuteReaderMultiple(multipleResult, connection, transaction, readerHander, cmdType, cmdText, cmdParms);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
@@ -618,6 +623,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(pool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
            pc.cmd.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
        public object[][] ExecuteArray(string cmdText, object parms = null) => ExecuteArray(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms));
 | 
			
		||||
        public object[][] ExecuteArray(DbTransaction transaction, string cmdText, object parms = null) => ExecuteArray(null, transaction, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms));
 | 
			
		||||
@@ -708,6 +714,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
            pc.cmd.Dispose();
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
        public object ExecuteScalar(string cmdText, object parms = null) => ExecuteScalar(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms));
 | 
			
		||||
@@ -743,6 +750,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
            pc.cmd.Dispose();
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -448,7 +448,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        //查从库
 | 
			
		||||
                        this.SlavePools : (
 | 
			
		||||
                        //查主库
 | 
			
		||||
                        slaveUnavailables == this.SlavePools.Count ? new List<ObjectPool<DbConnection>>() :
 | 
			
		||||
                        slaveUnavailables == this.SlavePools.Count ? new List<IObjectPool<DbConnection>>() :
 | 
			
		||||
                        //查从库可用
 | 
			
		||||
                        this.SlavePools.Where(sp => sp.IsAvailable).ToList());
 | 
			
		||||
                    if (availables.Any())
 | 
			
		||||
@@ -489,6 +489,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
                        }
 | 
			
		||||
                        LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
 | 
			
		||||
                        pc.cmd.Parameters.Clear();
 | 
			
		||||
                        pc.cmd.Dispose();
 | 
			
		||||
                        await ExecuteReaderMultipleAsync(multipleResult, connection, transaction, readerHander, cmdType, cmdText, cmdParms);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
@@ -551,6 +552,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(pool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
            pc.cmd.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
        public Task<object[][]> ExecuteArrayAsync(string cmdText, object parms = null) => ExecuteArrayAsync(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms));
 | 
			
		||||
        public Task<object[][]> ExecuteArrayAsync(DbTransaction transaction, string cmdText, object parms = null) => ExecuteArrayAsync(null, transaction, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms));
 | 
			
		||||
@@ -642,6 +644,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
            pc.cmd.Dispose();
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
        public Task<object> ExecuteScalarAsync(string cmdText, object parms = null) => ExecuteScalarAsync(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms));
 | 
			
		||||
@@ -677,6 +680,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            LoggerException(this.MasterPool, pc, ex, dt, logtxt);
 | 
			
		||||
            pc.cmd.Parameters.Clear();
 | 
			
		||||
            pc.cmd.Dispose();
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -136,7 +136,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
 | 
			
		||||
            ObjectPool<DbConnection>[] pools = null;
 | 
			
		||||
            IObjectPool<DbConnection>[] pools = null;
 | 
			
		||||
            for (var a = 0; a < 10; a++)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										134
									
								
								FreeSql/Internal/CommonProvider/AdoProvider/DbConnectionPool.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								FreeSql/Internal/CommonProvider/AdoProvider/DbConnectionPool.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
			
		||||
using SafeObjectPool;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Data;
 | 
			
		||||
using System.Data.Common;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace FreeSql.Internal.CommonProvider
 | 
			
		||||
{
 | 
			
		||||
    public class DbConnectionPool : IObjectPool<DbConnection>
 | 
			
		||||
    {
 | 
			
		||||
        internal DataType _dataType;
 | 
			
		||||
        internal Func<DbConnection> _connectionFactory;
 | 
			
		||||
        int _id;
 | 
			
		||||
        public DbConnectionPool(DataType dataType, Func<DbConnection> connectionFactory)
 | 
			
		||||
        {
 | 
			
		||||
            _dataType = dataType;
 | 
			
		||||
            _connectionFactory = connectionFactory;
 | 
			
		||||
            Policy = new DbConnectionPoolPolicy(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IPolicy<DbConnection> Policy { get; }
 | 
			
		||||
 | 
			
		||||
        public bool IsAvailable => true;
 | 
			
		||||
        public Exception UnavailableException => null;
 | 
			
		||||
        public DateTime? UnavailableTime => null;
 | 
			
		||||
        public string Statistics => "throw new NotImplementedException()";
 | 
			
		||||
        public string StatisticsFullily => "throw new NotImplementedException()";
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Object<DbConnection> Get(TimeSpan? timeout = null)
 | 
			
		||||
        {
 | 
			
		||||
            var conn = _connectionFactory();
 | 
			
		||||
            if (conn.State != ConnectionState.Open)
 | 
			
		||||
                conn.Open();
 | 
			
		||||
            return Object<DbConnection>.InitWith(this, Interlocked.Increment(ref _id), conn);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if net40
 | 
			
		||||
#else
 | 
			
		||||
        async public Task<Object<DbConnection>> GetAsync()
 | 
			
		||||
        {
 | 
			
		||||
            var conn = _connectionFactory();
 | 
			
		||||
            if (conn.State != ConnectionState.Open)
 | 
			
		||||
                await conn.OpenAsync();
 | 
			
		||||
            return Object<DbConnection>.InitWith(this, Interlocked.Increment(ref _id), conn);
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        public void Return(Object<DbConnection> obj, bool isReset = false)
 | 
			
		||||
        {
 | 
			
		||||
            if (obj == null) return;
 | 
			
		||||
            Policy.OnDestroy(obj.Value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool SetUnavailable(Exception exception)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal class DbConnectionPoolPolicy : IPolicy<DbConnection>
 | 
			
		||||
    {
 | 
			
		||||
        DbConnectionPool Pool;
 | 
			
		||||
        public DbConnectionPoolPolicy(DbConnectionPool pool)
 | 
			
		||||
        {
 | 
			
		||||
            this.Pool = pool;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string Name { get; set; } = typeof(DbConnectionPoolPolicy).GetType().FullName;
 | 
			
		||||
        public int PoolSize { get; set; } = 1000;
 | 
			
		||||
        public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
 | 
			
		||||
        public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(50);
 | 
			
		||||
        public int AsyncGetCapacity { get; set; } = 10000;
 | 
			
		||||
        public bool IsThrowGetTimeoutException { get; set; } = true;
 | 
			
		||||
        public int CheckAvailableInterval { get; set; } = 5;
 | 
			
		||||
 | 
			
		||||
        public DbConnection OnCreate()
 | 
			
		||||
        {
 | 
			
		||||
            var conn = Pool._connectionFactory();
 | 
			
		||||
            if (conn.State != ConnectionState.Open)
 | 
			
		||||
                conn.Open();
 | 
			
		||||
            return conn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnDestroy(DbConnection obj)
 | 
			
		||||
        {
 | 
			
		||||
            if (obj != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (obj.State != ConnectionState.Closed)
 | 
			
		||||
                    obj.Close();
 | 
			
		||||
                //obj.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnGet(Object<DbConnection> obj)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if net40
 | 
			
		||||
#else
 | 
			
		||||
        public Task OnGetAsync(Object<DbConnection> obj)
 | 
			
		||||
        {
 | 
			
		||||
            return Task.FromResult(true);
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        public void OnGetTimeout()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnReturn(Object<DbConnection> obj)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool OnCheckAvailable(Object<DbConnection> obj)
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnAvailable()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnUnavailable()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user