- 增加 Where In 表达式解析;

- 增加 FreeSqlBuilder.UseConnectionFactory 自定义数据库连接对象的创建方法;
This commit is contained in:
28810
2019-12-17 01:39:53 +08:00
parent 51494c31a2
commit e1e3e4a3b2
57 changed files with 1018 additions and 492 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View 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()
{
}
}
}