pgsql/mysql/sqlserver适配

This commit is contained in:
28810
2018-12-18 20:09:52 +08:00
commit 9b5e34032c
130 changed files with 12283 additions and 0 deletions

View File

@ -0,0 +1,267 @@
using Microsoft.Extensions.Logging;
using SafeObjectPool;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
namespace FreeSql.Internal.CommonProvider {
abstract partial class AdoProvider : IAdo {
protected abstract void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex);
protected abstract DbCommand CreateCommand();
protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
public bool IsTracePerformance { get; set; } = string.Compare(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), "Development", true) == 0;
public ObjectPool<DbConnection> MasterPool { get; protected set; }
public List<ObjectPool<DbConnection>> SlavePools { get; } = new List<ObjectPool<DbConnection>>();
protected ICache _cache { get; set; }
protected ILogger _log { get; set; }
protected int slaveUnavailables = 0;
private object slaveLock = new object();
private Random slaveRandom = new Random();
public AdoProvider(ICache cache, ILogger log) {
this._cache = cache;
this._log = log;
}
void LoggerException(ObjectPool<DbConnection> pool, DbCommand cmd, Exception e, DateTime dt, string logtxt, bool isThrowException = true) {
if (IsTracePerformance) {
TimeSpan ts = DateTime.Now.Subtract(dt);
if (e == null && ts.TotalMilliseconds > 100)
_log.LogWarning($"{pool.Policy.Name}执行SQL语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n{logtxt}");
}
if (e == null) return;
string log = $"{pool.Policy.Name}数据库出错执行SQL〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓\r\n{cmd.CommandText}\r\n";
foreach (DbParameter parm in cmd.Parameters)
log += parm.ParameterName.PadRight(20, ' ') + " = " + (parm.Value ?? "NULL") + "\r\n";
log += e.Message;
_log.LogError(log);
RollbackTransaction();
cmd.Parameters.Clear();
if (isThrowException) throw e;
}
public List<T> Query<T>(string sql, object parms = null) => Query<T>(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
public List<T> Query<T>(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
var names = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
var ds = new List<object[]>();
ExecuteReader(dr => {
if (names.Any() == false)
for (var a = 0; a < dr.FieldCount; a++) names.Add(dr.GetName(a), a);
object[] values = new object[dr.FieldCount];
dr.GetValues(values);
ds.Add(values);
}, cmdType, cmdText, cmdParms);
var ret = new List<T>();
foreach (var row in ds) {
var read = Utils.ExecuteArrayRowReadClassOrTuple(typeof(T), names, row);
ret.Add(read.value == null ? default(T) : (T) read.value);
}
return ret;
}
public void ExecuteReader(Action<DbDataReader> readerHander, string sql, object parms = null) => ExecuteReader(readerHander, CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
public void ExecuteReader(Action<DbDataReader> readerHander, CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
DateTime dt = DateTime.Now;
string logtxt = "";
DateTime logtxt_dt = DateTime.Now;
var pool = this.MasterPool;
bool isSlave = false;
//读写分离规则
if (this.SlavePools.Any() && cmdText.StartsWith("SELECT ", StringComparison.CurrentCultureIgnoreCase)) {
var availables = slaveUnavailables == 0 ?
//查从库
this.SlavePools : (
//查主库
slaveUnavailables == this.SlavePools.Count ? new List<ObjectPool<DbConnection>>() :
//查从库可用
this.SlavePools.Where(sp => sp.IsAvailable).ToList());
if (availables.Any()) {
isSlave = true;
pool = availables.Count == 1 ? availables[0] : availables[slaveRandom.Next(availables.Count)];
}
}
Object<DbConnection> conn = null;
var pc = PrepareCommand(cmdType, cmdText, cmdParms, ref logtxt);
if (IsTracePerformance) logtxt += $"PrepareCommand: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
Exception ex = null;
try {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
if (isSlave) {
//从库查询切换,恢复
bool isSlaveFail = false;
try {
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = pool.Get()).Value;
//if (slaveRandom.Next(100) % 2 == 0) throw new Exception("测试从库抛出异常");
} catch {
isSlaveFail = true;
}
if (isSlaveFail) {
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(pool, pc.cmd, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
pc.cmd.Parameters.Clear();
ExecuteReader(readerHander, cmdType, cmdText, cmdParms);
return;
}
} else {
//主库查询
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = pool.Get()).Value;
}
if (IsTracePerformance) {
logtxt += $"Open: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
logtxt_dt = DateTime.Now;
}
using (var dr = pc.cmd.ExecuteReader()) {
if (IsTracePerformance) logtxt += $"ExecuteReader: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
while (true) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
bool isread = dr.Read();
if (IsTracePerformance) logtxt += $" dr.Read: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
if (isread == false) break;
if (readerHander != null) {
object[] values = null;
if (IsTracePerformance) {
logtxt_dt = DateTime.Now;
values = new object[dr.FieldCount];
dr.GetValues(values);
logtxt += $" dr.GetValues: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
logtxt_dt = DateTime.Now;
}
readerHander(dr);
if (IsTracePerformance) logtxt += $" readerHander: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms ({string.Join(",", values)})\r\n";
}
}
if (IsTracePerformance) logtxt_dt = DateTime.Now;
dr.Close();
}
if (IsTracePerformance) logtxt += $"ExecuteReader_dispose: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
} catch (Exception ex2) {
ex = ex2;
}
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(pool, pc.cmd, ex, dt, logtxt);
pc.cmd.Parameters.Clear();
}
public object[][] ExecuteArray(string sql, object parms = null) => ExecuteArray(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
public object[][] ExecuteArray(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
List<object[]> ret = new List<object[]>();
ExecuteReader(dr => {
object[] values = new object[dr.FieldCount];
dr.GetValues(values);
ret.Add(values);
}, cmdType, cmdText, cmdParms);
return ret.ToArray();
}
public DataTable ExecuteDataTable(string sql, object parms = null) => ExecuteDataTable(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
public DataTable ExecuteDataTable(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
var ret = new DataTable();
ExecuteReader(dr => {
if (ret.Columns.Count == 0)
for (var a = 0; a < dr.FieldCount; a++) ret.Columns.Add(dr.GetName(a));
object[] values = new object[ret.Columns.Count];
dr.GetValues(values);
ret.Rows.Add(values);
}, cmdType, cmdText, cmdParms);
return ret;
}
public int ExecuteNonQuery(string sql, object parms = null) => ExecuteNonQuery(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
public int ExecuteNonQuery(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
DateTime dt = DateTime.Now;
string logtxt = "";
DateTime logtxt_dt = DateTime.Now;
Object<DbConnection> conn = null;
var pc = PrepareCommand(cmdType, cmdText, cmdParms, ref logtxt);
int val = 0;
Exception ex = null;
try {
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = this.MasterPool.Get()).Value;
val = pc.cmd.ExecuteNonQuery();
} catch (Exception ex2) {
ex = ex2;
}
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(this.MasterPool, pc.cmd, ex, dt, logtxt);
pc.cmd.Parameters.Clear();
return val;
}
public object ExecuteScalar(string sql, object parms = null) => ExecuteScalar(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
public object ExecuteScalar(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
DateTime dt = DateTime.Now;
string logtxt = "";
DateTime logtxt_dt = DateTime.Now;
Object<DbConnection> conn = null;
var pc = PrepareCommand(cmdType, cmdText, cmdParms, ref logtxt);
object val = null;
Exception ex = null;
try {
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = this.MasterPool.Get()).Value;
val = pc.cmd.ExecuteScalar();
} catch (Exception ex2) {
ex = ex2;
}
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(this.MasterPool, pc.cmd, ex, dt, logtxt);
pc.cmd.Parameters.Clear();
return val;
}
private (DbTransaction tran, DbCommand cmd) PrepareCommand(CommandType cmdType, string cmdText, DbParameter[] cmdParms, ref string logtxt) {
var dt = DateTime.Now;
DbCommand cmd = CreateCommand();
cmd.CommandType = cmdType;
cmd.CommandText = cmdText;
if (cmdParms != null) {
foreach (var parm in cmdParms) {
if (parm == null) continue;
if (parm.Value == null) parm.Value = DBNull.Value;
cmd.Parameters.Add(parm);
}
}
var tran = TransactionCurrentThread;
if (IsTracePerformance) logtxt += $" PrepareCommand_part1: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms cmdParms: {cmdParms.Length}\r\n";
if (tran != null) {
if (IsTracePerformance) dt = DateTime.Now;
cmd.Connection = tran.Connection;
cmd.Transaction = tran;
if (IsTracePerformance) logtxt += $" PrepareCommand_tran!=null: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
}
if (IsTracePerformance) dt = DateTime.Now;
AutoCommitTransaction();
if (IsTracePerformance) logtxt += $" AutoCommitTransaction: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
return (tran, cmd);
}
}
}

View File

@ -0,0 +1,215 @@
using SafeObjectPool;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
partial class AdoProvider {
public Task<List<T>> QueryAsync<T>(string sql, object parms = null) => QueryAsync<T>(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
async public Task<List<T>> QueryAsync<T>(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
var names = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
var ds = new List<object[]>();
await ExecuteReaderAsync(async dr => {
if (names.Any() == false)
for (var a = 0; a < dr.FieldCount; a++) names.Add(dr.GetName(a), a);
object[] values = new object[dr.FieldCount];
for (int a = 0; a < values.Length; a++) if (!await dr.IsDBNullAsync(a)) values[a] = await dr.GetFieldValueAsync<object>(a);
ds.Add(values);
}, cmdType, cmdText, cmdParms);
var ret = new List<T>();
foreach (var row in ds) {
var read = Utils.ExecuteArrayRowReadClassOrTuple(typeof(T), names, row);
ret.Add(read.value == null ? default(T) : (T) read.value);
}
return ret;
}
public Task ExecuteReaderAsync(Func<DbDataReader, Task> readerHander, string sql, object parms = null) => ExecuteReaderAsync(readerHander, CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
async public Task ExecuteReaderAsync(Func<DbDataReader, Task> readerHander, CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
DateTime dt = DateTime.Now;
string logtxt = "";
DateTime logtxt_dt = DateTime.Now;
var pool = this.MasterPool;
bool isSlave = false;
//读写分离规则
if (this.SlavePools.Any() && cmdText.StartsWith("SELECT ", StringComparison.CurrentCultureIgnoreCase)) {
var availables = slaveUnavailables == 0 ?
//查从库
this.SlavePools : (
//查主库
slaveUnavailables == this.SlavePools.Count ? new List<ObjectPool<DbConnection>>() :
//查从库可用
this.SlavePools.Where(sp => sp.IsAvailable).ToList());
if (availables.Any()) {
isSlave = true;
pool = availables.Count == 1 ? this.SlavePools[0] : availables[slaveRandom.Next(availables.Count)];
}
}
Object<DbConnection> conn = null;
var cmd = PrepareCommandAsync(cmdType, cmdText, cmdParms, ref logtxt);
if (IsTracePerformance) logtxt += $"PrepareCommand: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
Exception ex = null;
try {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
if (isSlave) {
//从库查询切换,恢复
bool isSlaveFail = false;
try {
if (cmd.Connection == null) cmd.Connection = (conn = await pool.GetAsync()).Value;
//if (slaveRandom.Next(100) % 2 == 0) throw new Exception("测试从库抛出异常");
} catch {
isSlaveFail = true;
}
if (isSlaveFail) {
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(pool, cmd, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
cmd.Parameters.Clear();
await ExecuteReaderAsync(readerHander, cmdType, cmdText, cmdParms);
return;
}
} else {
//主库查询
if (cmd.Connection == null) cmd.Connection = (conn = await pool.GetAsync()).Value;
}
if (IsTracePerformance) {
logtxt += $"Open: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
logtxt_dt = DateTime.Now;
}
using (var dr = await cmd.ExecuteReaderAsync()) {
if (IsTracePerformance) logtxt += $"ExecuteReader: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
while (true) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
bool isread = await dr.ReadAsync();
if (IsTracePerformance) logtxt += $" dr.Read: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
if (isread == false) break;
if (readerHander != null) {
object[] values = null;
if (IsTracePerformance) {
logtxt_dt = DateTime.Now;
values = new object[dr.FieldCount];
for (int a = 0; a < values.Length; a++) if (!await dr.IsDBNullAsync(a)) values[a] = await dr.GetFieldValueAsync<object>(a);
logtxt += $" dr.GetValues: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
logtxt_dt = DateTime.Now;
}
await readerHander(dr);
if (IsTracePerformance) logtxt += $" readerHander: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms ({string.Join(",", values)})\r\n";
}
}
if (IsTracePerformance) logtxt_dt = DateTime.Now;
dr.Close();
}
if (IsTracePerformance) logtxt += $"ExecuteReader_dispose: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
} catch (Exception ex2) {
ex = ex2;
}
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(pool, conn, ex); //pool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(pool, cmd, ex, dt, logtxt);
cmd.Parameters.Clear();
}
public Task ExecuteArrayAsync(string sql, object parms = null) => ExecuteArrayAsync(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
async public Task<object[][]> ExecuteArrayAsync(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
List<object[]> ret = new List<object[]>();
await ExecuteReaderAsync(async dr => {
object[] values = new object[dr.FieldCount];
for (int a = 0; a < values.Length; a++) if (!await dr.IsDBNullAsync(a)) values[a] = await dr.GetFieldValueAsync<object>(a);
ret.Add(values);
}, cmdType, cmdText, cmdParms);
return ret.ToArray();
}
public Task<DataTable> ExecuteDataTableAsync(string sql, object parms = null) => ExecuteDataTableAsync(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
async public Task<DataTable> ExecuteDataTableAsync(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
var ret = new DataTable();
await ExecuteReaderAsync(async dr => {
if (ret.Columns.Count == 0)
for (var a = 0; a < dr.FieldCount; a++) ret.Columns.Add(dr.GetName(a));
object[] values = new object[ret.Columns.Count];
for (int a = 0; a < values.Length; a++) if (!await dr.IsDBNullAsync(a)) values[a] = await dr.GetFieldValueAsync<object>(a);
ret.Rows.Add(values);
}, cmdType, cmdText, cmdParms);
return ret;
}
public Task<int> ExecuteNonQueryAsync(string sql, object parms = null) => ExecuteNonQueryAsync(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
async public Task<int> ExecuteNonQueryAsync(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
DateTime dt = DateTime.Now;
string logtxt = "";
Object<DbConnection> conn = null;
var cmd = PrepareCommandAsync(cmdType, cmdText, cmdParms, ref logtxt);
var logtxt_dt = DateTime.Now;
int val = 0;
Exception ex = null;
try {
if (cmd.Connection == null) cmd.Connection = (conn = await this.MasterPool.GetAsync()).Value;
val = await cmd.ExecuteNonQueryAsync();
} catch (Exception ex2) {
ex = ex2;
}
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(this.MasterPool, cmd, ex, dt, logtxt);
cmd.Parameters.Clear();
return val;
}
public Task<object> ExecuteScalarAsync(string sql, object parms = null) => ExecuteScalarAsync(CommandType.Text, sql, GetDbParamtersByObject(sql, parms));
async public Task<object> ExecuteScalarAsync(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) {
var dt = DateTime.Now;
var logtxt = "";
Object<DbConnection> conn = null;
var cmd = PrepareCommandAsync(cmdType, cmdText, cmdParms, ref logtxt);
var logtxt_dt = DateTime.Now;
object val = null;
Exception ex = null;
try {
if (cmd.Connection == null) cmd.Connection = (conn = await this.MasterPool.GetAsync()).Value;
val = await cmd.ExecuteScalarAsync();
} catch (Exception ex2) {
ex = ex2;
}
if (conn != null) {
if (IsTracePerformance) logtxt_dt = DateTime.Now;
ReturnConnection(MasterPool, conn, ex); //this.MasterPool.Return(conn, ex);
if (IsTracePerformance) logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
LoggerException(this.MasterPool, cmd, ex, dt, logtxt);
cmd.Parameters.Clear();
return val;
}
private DbCommand PrepareCommandAsync(CommandType cmdType, string cmdText, DbParameter[] cmdParms, ref string logtxt) {
DateTime dt = DateTime.Now;
DbCommand cmd = CreateCommand();
cmd.CommandType = cmdType;
cmd.CommandText = cmdText;
if (cmdParms != null) {
foreach (var parm in cmdParms) {
if (parm == null) continue;
if (parm.Value == null) parm.Value = DBNull.Value;
cmd.Parameters.Add(parm);
}
}
if (IsTracePerformance) logtxt += $" PrepareCommand_tran==null: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
return cmd;
}
}
}

View File

@ -0,0 +1,152 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SafeObjectPool;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Threading;
namespace FreeSql.Internal.CommonProvider {
partial class AdoProvider {
class Transaction2 {
internal Object<DbConnection> Conn;
internal DbTransaction Transaction;
internal DateTime RunTime;
internal TimeSpan Timeout;
public Transaction2(Object<DbConnection> conn, DbTransaction tran, TimeSpan timeout) {
Conn = conn;
Transaction = tran;
RunTime = DateTime.Now;
Timeout = timeout;
}
}
private Dictionary<int, Transaction2> _trans = new Dictionary<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;
private Dictionary<int, List<string>> _preRemoveKeys = new Dictionary<int, List<string>>();
private object _preRemoveKeys_lock = new object();
public string[] PreRemove(params string[] key) {
var tid = Thread.CurrentThread.ManagedThreadId;
List<string> keys = null;
if (key == null || key.Any() == false) return _preRemoveKeys.TryGetValue(tid, out keys) ? keys.ToArray() : new string[0];
_log.LogDebug($"线程{tid}事务预删除 {JsonConvert.SerializeObject(key)}");
if (_preRemoveKeys.TryGetValue(tid, out keys) == false)
lock (_preRemoveKeys_lock)
if (_preRemoveKeys.TryGetValue(tid, out keys) == false) {
_preRemoveKeys.Add(tid, keys = new List<string>(key));
return key;
}
keys.AddRange(key);
return keys.ToArray();
}
public void TransactionPreRemoveCache(params string[] key) => PreRemove(key);
/// <summary>
/// 启动事务
/// </summary>
public void BeginTransaction(TimeSpan timeout) {
int tid = Thread.CurrentThread.ManagedThreadId;
Transaction2 tran = null;
Object<DbConnection> conn = null;
try {
conn = MasterPool.Get();
tran = new Transaction2(conn, conn.Value.BeginTransaction(), timeout);
} catch(Exception ex) {
_log.LogError($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}");
throw ex;
}
if (_trans.ContainsKey(tid)) CommitTransaction();
lock (_trans_lock)
_trans.Add(tid, tran);
}
/// <summary>
/// 自动提交事务
/// </summary>
private void AutoCommitTransaction() {
if (_trans.Count > 0) {
Transaction2[] trans = null;
lock (_trans_lock)
trans = _trans.Values.Where(st2 => DateTime.Now.Subtract(st2.RunTime) > st2.Timeout).ToArray();
foreach (Transaction2 tran in trans) CommitTransaction(true, tran);
}
}
private void CommitTransaction(bool isCommit, Transaction2 tran) {
if (tran == null || tran.Transaction == null || tran.Transaction.Connection == null) return;
if (_trans.ContainsKey(tran.Conn.LastGetThreadId))
lock (_trans_lock)
if (_trans.ContainsKey(tran.Conn.LastGetThreadId))
_trans.Remove(tran.Conn.LastGetThreadId);
var removeKeys = PreRemove();
if (_preRemoveKeys.ContainsKey(tran.Conn.LastGetThreadId))
lock (_preRemoveKeys_lock)
if (_preRemoveKeys.ContainsKey(tran.Conn.LastGetThreadId))
_preRemoveKeys.Remove(tran.Conn.LastGetThreadId);
Exception ex = null;
var f001 = isCommit ? "提交" : "回滚";
try {
_log.LogDebug($"线程{tran.Conn.LastGetThreadId}事务{f001}批量删除缓存key {Newtonsoft.Json.JsonConvert.SerializeObject(removeKeys)}");
_cache.Remove(removeKeys);
if (isCommit) tran.Transaction.Commit();
else tran.Transaction.Rollback();
} catch (Exception ex2) {
ex = ex2;
_log.LogError($"数据库出错({f001}事务):{ex.Message} {ex.StackTrace}");
} finally {
ReturnConnection(MasterPool, tran.Conn, ex); //MasterPool.Return(tran.Conn, ex);
}
}
private void CommitTransaction(bool isCommit) {
if (_trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var tran)) CommitTransaction(isCommit, tran);
}
/// <summary>
/// 提交事务
/// </summary>
public void CommitTransaction() => CommitTransaction(true);
/// <summary>
/// 回滚事务
/// </summary>
public void RollbackTransaction() => CommitTransaction(false);
public void Dispose() {
Transaction2[] trans = null;
lock (_trans_lock)
trans = _trans.Values.ToArray();
foreach (Transaction2 tran in trans) CommitTransaction(false, tran);
}
/// <summary>
/// 开启事务不支持异步60秒未执行完将自动提交
/// </summary>
/// <param name="handler">事务体 () => {}</param>
public void Transaction(Action handler) {
Transaction(handler, TimeSpan.FromSeconds(60));
}
/// <summary>
/// 开启事务(不支持异步)
/// </summary>
/// <param name="handler">事务体 () => {}</param>
/// <param name="timeout">超时,未执行完将自动提交</param>
public void Transaction(Action handler, TimeSpan timeout) {
try {
BeginTransaction(timeout);
handler();
CommitTransaction();
} catch (Exception ex) {
RollbackTransaction();
throw ex;
}
}
}
}

View File

@ -0,0 +1,19 @@
using System.Text.RegularExpressions;
namespace FreeSql.Internal.CommonProvider {
partial class AdoProvider {
public abstract object AddslashesProcessParam(object param);
public string Addslashes(string filter, params object[] parms) {
if (filter == null || parms == null) return string.Empty;
if (parms.Length == 0) return filter;
var nparms = new object[parms.Length];
for (int a = 0; a < parms.Length; a++) {
if (parms[a] == null)
filter = Regex.Replace(filter, @"\s*(=|IN)\s*\{" + a + @"\}", " IS {" + a + "}", RegexOptions.IgnoreCase);
nparms[a] = AddslashesProcessParam(parms[a]);
}
try { string ret = string.Format(filter, nparms); return ret; } catch { return filter; }
}
}
}

View File

@ -0,0 +1,176 @@
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
class CacheProvider : ICache {
public IDistributedCache Cache { get; private set; }
private bool CacheSupportMultiRemove = false;
private static DateTime dt1970 = new DateTime(1970, 1, 1);
public CacheProvider(IDistributedCache cache, ILogger log) {
if (cache == null) cache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions { }));
Cache = cache;
var key1 = $"testCacheSupportMultiRemoveFreeSql{Guid.NewGuid().ToString("N")}";
var key2 = $"testCacheSupportMultiRemoveFreeSql{Guid.NewGuid().ToString("N")}";
Cache.Set(key1, new byte[] { 65 });
Cache.Set(key2, new byte[] { 65 });
try { Cache.Remove($"{key1}|{key2}"); } catch { } // redis-cluster 不允许执行 multi keys 命令
CacheSupportMultiRemove = Cache.Get(key1) == null && cache.Get(key2) == null;
if (CacheSupportMultiRemove == false) {
log.LogWarning("FreeSql Warning: 低性能, IDistributedCache 没现实批量删除缓存 Cache.Remove(\"key1|key2\").");
Remove(key1, key2);
}
}
public Func<object, string> Serialize { get; set; }
public Func<string, Type, object> Deserialize { get; set; }
Func<JsonSerializerSettings> JsonSerializerSettings = () => {
var st = new JsonSerializerSettings();
st.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
st.DateFormatHandling = DateFormatHandling.IsoDateFormat;
st.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
return st;
};
string SerializeObject(object value) {
if (Serialize != null) return Serialize(value);
return JsonConvert.SerializeObject(value, this.JsonSerializerSettings());
}
T DeserializeObject<T>(string value) {
if (Deserialize != null) return (T) Deserialize(value, typeof(T));
return JsonConvert.DeserializeObject<T>(value, this.JsonSerializerSettings());
}
public void Set<T>(string key, T data, int timeoutSeconds = 0) {
if (string.IsNullOrEmpty(key)) return;
Cache.Set(key, Encoding.UTF8.GetBytes(this.SerializeObject(data)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
}
public T Get<T>(string key) {
if (string.IsNullOrEmpty(key)) return default(T);
var value = Cache.Get(key);
if (value == null) return default(T);
return this.DeserializeObject<T>(Encoding.UTF8.GetString(value));
}
public string Get(string key) {
if (string.IsNullOrEmpty(key)) return null;
var value = Cache.Get(key);
if (value == null) return null;
return Encoding.UTF8.GetString(value);
}
async public Task SetAsync<T>(string key, T data, int timeoutSeconds = 0) {
if (string.IsNullOrEmpty(key)) return;
await Cache.SetAsync(key, Encoding.UTF8.GetBytes(this.SerializeObject(data)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
}
async public Task<T> GetAsync<T>(string key) {
if (string.IsNullOrEmpty(key)) return default(T);
var value = await Cache.GetAsync(key);
if (value == null) return default(T);
return this.DeserializeObject<T>(Encoding.UTF8.GetString(value));
}
async public Task<string> GetAsync(string key) {
if (string.IsNullOrEmpty(key)) return null;
var value = await Cache.GetAsync(key);
if (value == null) return null;
return Encoding.UTF8.GetString(value);
}
public void Remove(params string[] keys) {
if (keys == null || keys.Length == 0) return;
var keysDistinct = keys.Distinct();
if (CacheSupportMultiRemove) Cache.Remove(string.Join("|", keysDistinct));
else foreach (var key in keysDistinct) Cache.Remove(key);
}
async public Task RemoveAsync(params string[] keys) {
if (keys == null || keys.Length == 0) return;
var keysDistinct = keys.Distinct();
if (CacheSupportMultiRemove) await Cache.RemoveAsync(string.Join("|", keysDistinct));
else foreach (var key in keysDistinct) await Cache.RemoveAsync(key);
}
public T Shell<T>(string key, int timeoutSeconds, Func<T> getData) {
if (timeoutSeconds <= 0) return getData();
if (Cache == null) throw new Exception("缓存现实 IDistributedCache 为 null");
var cacheValue = Cache.Get(key);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
return DeserializeObject<T>(txt);
} catch {
Cache.Remove(key);
throw;
}
}
var ret = getData();
Cache.Set(key, Encoding.UTF8.GetBytes(SerializeObject(ret)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
return ret;
}
public T Shell<T>(string key, string field, int timeoutSeconds, Func<T> getData) {
if (timeoutSeconds <= 0) return getData();
if (Cache == null) throw new Exception("缓存现实 IDistributedCache 为 null");
var hashkey = $"{key}:{field}";
var cacheValue = Cache.Get(hashkey);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
var value = DeserializeObject<(T, long)>(txt);
if (DateTime.Now.Subtract(dt1970.AddSeconds(value.Item2)).TotalSeconds <= timeoutSeconds) return value.Item1;
} catch {
Cache.Remove(hashkey);
throw;
}
}
var ret = (getData(), (long) DateTime.Now.Subtract(dt1970).TotalSeconds);
Cache.Set(hashkey, Encoding.UTF8.GetBytes(SerializeObject(ret)));
return ret.Item1;
}
async public Task<T> ShellAsync<T>(string key, int timeoutSeconds, Func<Task<T>> getDataAsync) {
if (timeoutSeconds <= 0) return await getDataAsync();
if (Cache == null) throw new Exception("缓存现实 IDistributedCache 为 null");
var cacheValue = await Cache.GetAsync(key);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
return DeserializeObject<T>(txt);
} catch {
await Cache.RemoveAsync(key);
throw;
}
}
var ret = await getDataAsync();
await Cache.SetAsync(key, Encoding.UTF8.GetBytes(SerializeObject(ret)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
return ret;
}
async public Task<T> ShellAsync<T>(string key, string field, int timeoutSeconds, Func<Task<T>> getDataAsync) {
if (timeoutSeconds <= 0) return await getDataAsync();
if (Cache == null) throw new Exception("缓存现实 IDistributedCache 为 null");
var hashkey = $"{key}:{field}";
var cacheValue = await Cache.GetAsync(hashkey);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
var value = DeserializeObject<(T, long)>(txt);
if (DateTime.Now.Subtract(dt1970.AddSeconds(value.Item2)).TotalSeconds <= timeoutSeconds) return value.Item1;
} catch {
await Cache.RemoveAsync(hashkey);
throw;
}
}
var ret = (await getDataAsync(), (long) DateTime.Now.Subtract(dt1970).TotalSeconds);
await Cache.SetAsync(hashkey, Encoding.UTF8.GetBytes(SerializeObject(ret)));
return ret.Item1;
}
}
}

View File

@ -0,0 +1,52 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Internal.CommonProvider {
abstract partial class DeleteProvider<T1> : IDelete<T1> where T1 : class {
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
protected List<T1> _source = new List<T1>();
protected TableInfo _table;
protected StringBuilder _where = new StringBuilder();
protected int _whereTimes = 0;
protected List<DbParameter> _params = new List<DbParameter>();
public DeleteProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
_where.Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append(" WHERE ");
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T1>();
}
public long ExecuteAffrows() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
return _orm.Ado.ExecuteNonQuery(CommandType.Text, sql, _params.ToArray());
}
public abstract List<T1> ExecuteDeleted();
public IDelete<T1> Where(Expression<Func<T1, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, exp?.Body));
public IDelete<T1> Where(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this;
if (++_whereTimes > 1) _where.Append(" AND ");
_where.Append("(").Append(sql).Append(")");
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this;
}
public IDelete<T1> Where(T1 item) => this.Where(new[] { item });
public IDelete<T1> Where(IEnumerable<T1> items) => this.Where(_commonUtils.WhereItems(_table, "", items));
public IDelete<T1> WhereExists<TEntity2>(ISelect<TEntity2> select, bool notExists = false) where TEntity2 : class => this.Where($"{(notExists ? "NOT " : "")}EXISTS({select.ToSql("1")})");
public string ToSql() => _whereTimes <= 0 ? null : _where.ToString();
}
}

View File

@ -0,0 +1,90 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Internal.CommonProvider {
abstract partial class InsertProvider<T1> : IInsert<T1> where T1 : class {
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
protected List<T1> _source = new List<T1>();
protected Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected TableInfo _table;
protected DbParameter[] _params;
public InsertProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T1>();
}
public IInsert<T1> AppendData(T1 source) {
if (source != null) _source.Add(source);
return this;
}
public IInsert<T1> AppendData(IEnumerable<T1> source) {
if (source != null) _source.AddRange(source.Where(a => a != null));
return this;
}
public long ExecuteAffrows() => _orm.Ado.ExecuteNonQuery(CommandType.Text, this.ToSql(), _params);
public abstract long ExecuteIdentity();
public abstract List<T1> ExecuteInserted();
public IInsert<T1> IgnoreColumns(Expression<Func<T1, object>> columns) {
var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false).Distinct();
_ignore.Clear();
foreach (var col in cols) _ignore.Add(col, true);
return this;
}
public IInsert<T1> InsertColumns(Expression<Func<T1, object>> columns) {
var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false).ToDictionary(a => a, a => true);
_ignore.Clear();
foreach (var col in _table.Columns.Values)
if (cols.ContainsKey(col.Attribute.Name) == false)
_ignore.Add(col.Attribute.Name, true);
return this;
}
public string ToSql() {
if (_source == null || _source.Any() == false) return null;
var sb = new StringBuilder();
sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append("(");
var colidx = 0;
foreach (var col in _table.Columns.Values)
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name));
++colidx;
}
if (colidx == 0) return null;
sb.Append(") VALUES");
_params = new DbParameter[colidx * _source.Count];
var didx = 0;
foreach (var d in _source) {
if (didx > 0) sb.Append(", ");
sb.Append("(");
var colidx2 = 0;
foreach (var col in _table.Columns.Values)
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
if (colidx2 > 0) sb.Append(", ");
sb.Append("?").Append(col.CsName).Append(didx);
_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}{didx}", _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : DBNull.Value);
++colidx2;
}
sb.Append(")");
++didx;
}
return sb.ToString();
}
}
}

View File

@ -0,0 +1,263 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace FreeSql.Internal.CommonProvider {
abstract class Select0Provider<TSelect, T1> : ISelect0<TSelect, T1> where TSelect : class where T1 : class {
protected int _limit, _skip;
protected string _select = "SELECT ", _orderby, _groupby, _having;
protected StringBuilder _where = new StringBuilder();
protected List<DbParameter> _params = new List<DbParameter>();
protected List<SelectTableInfo> _tables = new List<SelectTableInfo>();
protected StringBuilder _join = new StringBuilder();
protected (int seconds, string key) _cache = (0, null);
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
internal static void CopyData(Select0Provider<TSelect, T1> from, object to) {
var toType = to?.GetType();
if (toType == null) return;
toType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._limit);
toType.GetField("_skip", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._skip);
toType.GetField("_select", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._select);
toType.GetField("_where", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._where.ToString()));
toType.GetField("_params", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<DbParameter>(from._params.ToArray()));
toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<SelectTableInfo>(from._tables.ToArray()));
toType.GetField("_join", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._join.ToString()));
toType.GetField("_cache", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._cache);
//toType.GetField("_orm", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._orm);
//toType.GetField("_commonUtils", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonUtils);
//toType.GetField("_commonExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonExpression);
}
public Select0Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_tables.Add(new SelectTableInfo { Table = _commonUtils.GetTableByEntity(typeof(T1)), Alias = "a", On = null, Type = SelectTableInfoType.From });
this.Where(_commonUtils.WhereObject(_tables.First().Table, "a.", dywhere));
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T1>();
}
public bool Any() {
this.Limit(1);
return this.ToList<int>("1").FirstOrDefault() == 1;
}
public TSelect Caching(int seconds, string key = null) {
_cache = (seconds, key);
return this as TSelect;
}
public long Count() => this.ToList<int>("count(1)").FirstOrDefault();
public TSelect Count(out long count) {
count = this.Count();
return this as TSelect;
}
public TSelect GroupBy(string sql, object parms = null) {
_groupby = sql;
if (string.IsNullOrEmpty(_groupby)) return this as TSelect;
_groupby = string.Concat(" \r\nGROUP BY ", _groupby);
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(_groupby, parms));
return this as TSelect;
}
public TSelect Having(string sql, object parms = null) {
if (string.IsNullOrEmpty(_groupby) || string.IsNullOrEmpty(sql)) return this as TSelect;
_having = string.Concat(_having, " AND (", sql, ")");
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this as TSelect;
}
public TSelect LeftJoin(Expression<Func<T1, bool>> exp) => this.InternalJoin(exp?.Body, SelectTableInfoType.LeftJoin);
public TSelect InnerJoin(Expression<Func<T1, bool>> exp) => this.InternalJoin(exp?.Body, SelectTableInfoType.InnerJoin);
public TSelect RightJoin(Expression<Func<T1, bool>> exp) => this.InternalJoin(exp?.Body, SelectTableInfoType.RightJoin);
public TSelect LeftJoin<T2>(Expression<Func<T1, T2, bool>> exp) => this.InternalJoin(exp?.Body, SelectTableInfoType.LeftJoin);
public TSelect InnerJoin<T2>(Expression<Func<T1, T2, bool>> exp) => this.InternalJoin(exp?.Body, SelectTableInfoType.InnerJoin);
public TSelect RightJoin<T2>(Expression<Func<T1, T2, bool>> exp) => this.InternalJoin(exp?.Body, SelectTableInfoType.RightJoin);
public TSelect InnerJoin(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this as TSelect;
_join.Append(" \r\nINNER JOIN ").Append(sql);
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this as TSelect;
}
public TSelect LeftJoin(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this as TSelect;
_join.Append(" \r\nLEFT JOIN ").Append(sql);
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this as TSelect;
}
public TSelect Limit(int limit) {
_limit = limit;
return this as TSelect;
}
public TSelect Master() {
_select = " SELECT ";
return this as TSelect;
}
public TSelect Offset(int offset) => this.Skip(offset) as TSelect;
public TSelect OrderBy(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) _orderby = null;
_orderby = string.Concat(string.IsNullOrEmpty(_orderby) ? " \r\nORDER BY " : "", _orderby, sql);
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this as TSelect;
}
public TSelect Page(int pageIndex, int pageSize) {
this.Skip(Math.Max(0, pageIndex - 1) * pageSize);
return this.Limit(pageSize) as TSelect;
}
public TSelect RightJoin(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this as TSelect;
_join.Append(" \r\nRIGHT JOIN ").Append(sql);
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this as TSelect;
}
public TSelect Skip(int offset) {
_skip = offset;
return this as TSelect;
}
public TSelect Take(int limit) => this.Limit(limit) as TSelect;
public List<TTuple> ToList<TTuple>(string field) {
var sql = this.ToSql(field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql;
return _orm.Cache.Shell(_cache.key, _cache.seconds, () => {
List<TTuple> ret = new List<TTuple>();
Type type = typeof(TTuple);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql, _params.ToArray());
foreach (var dr in ds) {
var read = Utils.ExecuteArrayRowReadClassOrTuple(type, null, dr);
ret.Add(read.value == null ? default(TTuple) : (TTuple)read.value);
}
return ret;
});
}
public List<T1> ToList() {
return this.ToList<T1>(this.GetAllField());
}
public T1 ToOne() {
this.Limit(1);
return ToList().FirstOrDefault();
}
protected List<TReturn> ToList<TReturn>((ReadAnonymousTypeInfo map, string field) af) {
var sql = this.ToSql(af.field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
var drarr = _orm.Cache.Shell(_cache.key, _cache.seconds, () => _orm.Ado.ExecuteArray(CommandType.Text, sql, _params.ToArray()));
var ret = new List<TReturn>();
for (var a = 0; a < drarr.Length; a++) {
var dr = drarr[a];
var index = -1;
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index));
}
return ret;
}
protected (ReadAnonymousTypeInfo map, string field) GetNewExpressionField(NewExpression newexp) {
var map = new ReadAnonymousTypeInfo();
var field = new StringBuilder();
var index = 0;
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp);
return (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null);
}
protected (ReadAnonymousTypeInfo map, string field) GetAllField() {
var type = typeof(T1);
var map = new ReadAnonymousTypeInfo { Consturctor = type.GetConstructor(new Type[0]), ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties };
var field = new StringBuilder();
var tb = _tables.First();
var index = 0;
var ps = typeof(T1).GetProperties();
foreach (var p in ps) {
var child = new ReadAnonymousTypeInfo { CsName = p.Name };
if (tb.Table.ColumnsByCs.TryGetValue(p.Name, out var col)) { //普通字段
if (index > 0) field.Append(", ");
field.Append(tb.Alias).Append(".").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" as").Append(++index);
} else {
var tb2 = _tables.Where(a => a.Table.Type == p.PropertyType && a.Alias.Contains(p.Name)).FirstOrDefault();
if (tb2 == null && ps.Where(pw => pw.PropertyType == p.PropertyType).Count() == 1) tb2 = _tables.Where(a => a.Table.Type == p.PropertyType).FirstOrDefault();
if (tb2 == null) continue;
child.Consturctor = tb2.Table.Type.GetConstructor(new Type[0]);
child.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
foreach (var col2 in tb2.Table.Columns.Values) {
if (index > 0) field.Append(", ");
field.Append(tb2.Alias).Append(".").Append(_commonUtils.QuoteSqlName(col2.Attribute.Name)).Append(" as").Append(++index);
child.Childs.Add(new ReadAnonymousTypeInfo { CsName = col2.CsName });
}
}
map.Childs.Add(child);
}
return (map, field.ToString());
}
public abstract string ToSql(string field = null);
public TSelect Where(string sql, object parms = null) => this.WhereIf(true, sql, parms);
public TSelect WhereIf(bool condition, string sql, object parms = null) {
if (condition == false || string.IsNullOrEmpty(sql)) return this as TSelect;
_where.Append(" AND (").Append(sql).Append(")");
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this as TSelect;
}
#region common
protected TMember InternalAvg<TMember>(Expression exp) => this.ToList<TMember>($"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
protected TMember InternalMax<TMember>(Expression exp) => this.ToList<TMember>($"max({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
protected TMember InternalMin<TMember>(Expression exp) => this.ToList<TMember>($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
protected TMember InternalSum<TMember>(Expression exp) => this.ToList<TMember>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
protected TSelect InternalGroupBy(Expression columns) => this.GroupBy(string.Join(", ", _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, columns, true)));
protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType) {
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp);
return this as TSelect;
}
protected TSelect InternalJoin<T2>(Expression exp, SelectTableInfoType joinType) {
var tb = _commonUtils.GetTableByEntity(typeof(T2));
if (tb == null) throw new ArgumentException("T2 类型错误");
_tables.Add(new SelectTableInfo { Table = tb, Alias = $"IJ{_tables.Count}", On = null, Type = joinType });
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp);
return this as TSelect;
}
protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true));
protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true)} DESC");
protected List<TReturn> InternalToList<TReturn>(Expression select) => this.ToList<TReturn>(this.GetNewExpressionField(select as NewExpression));
protected TSelect InternalWhere(Expression exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp));
protected TSelect InternalWhereLikeOr(Expression columns, string pattern, bool notLike) {
if (string.IsNullOrEmpty(pattern)) return this as TSelect;
var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, columns, true);
if (cols.Any() == false) return this as TSelect;
var filter = "";
foreach (var col in cols) {
if (string.IsNullOrEmpty(col)) continue;
filter += string.Concat(" OR ", _commonUtils.FormatSql($"{col} {(notLike ? "NOT LIKE" : "LIKE")} {{0}}", pattern));
}
if (string.IsNullOrEmpty(filter)) return this as TSelect;
return this.Where(filter.Substring(4));
}
protected TSelect InternalWhereLike(Expression column, string pattern, bool notLike) {
if (string.IsNullOrEmpty(pattern)) return this as TSelect;
string col = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true);
if (string.IsNullOrEmpty(col)) return this as TSelect;
return this.Where(_commonUtils.FormatSql($"{col} {(notLike ? "NOT LIKE" : "LIKE")} {{0}}", pattern));
}
protected TSelect InternalJoin(Expression exp) {
return this as TSelect;
}
#endregion
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
where T1 : class
where T2 : class
where T3 : class
where T4 : class
where T5 : class
where T6 : class
where T7 : class
where T8 : class
where T9 : class
where T10 : class {
public Select10Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10));
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Min<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Sum<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,114 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select1Provider<T1> : Select0Provider<ISelect<T1>, T1>, ISelect<T1>
where T1 : class {
public Select1Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
}
protected ISelect<T1> InternalFrom(Expression exp) {
if (exp.NodeType == ExpressionType.Call) {
var expCall = exp as MethodCallExpression;
var stockCall = new Stack<MethodCallExpression>();
while (expCall != null) {
stockCall.Push(expCall);
expCall = expCall.Object as MethodCallExpression;
}
while (stockCall.Any()) {
expCall = stockCall.Pop();
switch (expCall.Method.Name) {
case "Where": this.InternalWhere(expCall.Arguments[0]); break;
case "WhereIf":
if (_commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[0], false) == "1")
this.InternalWhere(expCall.Arguments[1]);
break;
case "WhereLike":
var whereLikeArg0 = (expCall.Arguments[0] as UnaryExpression).Operand as LambdaExpression;
var whereLikeArg1 = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[1], false);
var whereLikeArg2 = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[2], false) == "1";
if (whereLikeArg0.ReturnType == typeof(string)) this.InternalWhereLike(whereLikeArg0, whereLikeArg1, whereLikeArg2);
else this.InternalWhereLikeOr(whereLikeArg0, whereLikeArg1, whereLikeArg2);
break;
case "GroupBy": this.InternalGroupBy(expCall.Arguments[0]); break;
case "OrderBy": this.InternalOrderBy(expCall.Arguments[0]); break;
case "OrderByDescending": this.InternalOrderByDescending(expCall.Arguments[0]); break;
case "LeftJoin": this.InternalJoin(expCall.Arguments[0], SelectTableInfoType.LeftJoin); break;
case "InnerJoin": this.InternalJoin(expCall.Arguments[0], SelectTableInfoType.InnerJoin); break;
case "RightJoin": this.InternalJoin(expCall.Arguments[0], SelectTableInfoType.RightJoin); break;
default: throw new NotImplementedException($"未现实 {expCall.Method.Name}");
}
}
return this;
}
throw new NotImplementedException($"未现实 {exp}");
}
public ISelect<T1> As(string alias) {
var oldAs = _tables.First().Alias;
var newAs = string.IsNullOrEmpty(alias) ? "a" : alias;
if (oldAs != newAs) {
_tables.First().Alias = newAs;
var wh = _where.ToString();
_where.Replace($" {oldAs}.", $" {newAs}.");
}
return this;
}
public TMember Avg<TMember>(Expression<Func<T1, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
public abstract ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class;// { this.InternalFrom(exp?.Body); var ret = new Select3Provider<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public abstract ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class;// { this.InternalFrom(exp?.Body); var ret = new Select4Provider<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public abstract ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class;// { this.InternalFrom(exp?.Body); var ret = new Select5Provider<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public abstract ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class;// { this.InternalFrom(exp?.Body); var ret = new Select6Provider<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class;// { this.InternalFrom(exp?.Body); var ret = new Select7Provider<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class;// { this.InternalFrom(exp?.Body); var ret = new Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class;// { this.InternalFrom(exp?.Body); var ret = new Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class;// { this.InternalFrom(exp?.Body); var ret = new Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
public ISelect<T1> GroupBy(Expression<Func<T1, object>> columns) => this.InternalGroupBy(columns?.Body);
public TMember Max<TMember>(Expression<Func<T1, TMember>> column) => this.InternalMax<TMember>(column?.Body);
public TMember Min<TMember>(Expression<Func<T1, TMember>> column) => this.InternalMin<TMember>(column?.Body);
public ISelect<T1> OrderBy<TMember>(Expression<Func<T1, TMember>> column) => this.InternalOrderBy(column?.Body);
public ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column) => this.InternalOrderByDescending(column?.Body);
public TMember Sum<TMember>(Expression<Func<T1, TMember>> column) => this.InternalSum<TMember>(column?.Body);
public List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
public ISelect<T1> Where(Expression<Func<T1, bool>> exp) => this.InternalWhere(exp?.Body);
public ISelect<T1> Where<T2>(Expression<Func<T1, T2, bool>> exp) where T2 : class => this.InternalWhere(exp?.Body);
public ISelect<T1> Where<T2, T3>(Expression<Func<T1, T2, T3, bool>> exp) where T2 : class where T3 : class => this.InternalWhere(exp?.Body);
public ISelect<T1> Where<T2, T3, T4>(Expression<Func<T1, T2, T3, T4, bool>> exp) where T2 : class where T3 : class where T4 : class => this.InternalWhere(exp?.Body);
public ISelect<T1> Where<T2, T3, T4, T5>(Expression<Func<T1, T2, T3, T4, T5, bool>> exp) where T2 : class where T3 : class where T4 : class where T5 : class => this.InternalWhere(exp?.Body);
public ISelect<T1> WhereIf(bool condition, Expression<Func<T1, bool>> exp) => condition ? this.InternalWhere(exp?.Body) : this;
public ISelect<T1> WhereLike(Expression<Func<T1, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
public ISelect<T1> WhereLike(Expression<Func<T1, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select2Provider<T1, T2> : Select0Provider<ISelect<T1, T2>, T1>, ISelect<T1, T2>
where T1 : class
where T2 : class {
public Select2Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T2>();
}
TMember ISelect<T1, T2>.Avg<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2> ISelect<T1, T2>.GroupBy(Expression<Func<T1, T2, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2>.Max<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2>.Min<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2> ISelect<T1, T2>.OrderBy<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2> ISelect<T1, T2>.OrderByDescending<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2>.Sum<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2>.ToList<TReturn>(Expression<Func<T1, T2, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2> ISelect<T1, T2>.Where(Expression<Func<T1, T2, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2> ISelect<T1, T2>.WhereIf(bool condition, Expression<Func<T1, T2, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2> ISelect<T1, T2>.WhereLike(Expression<Func<T1, T2, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2> ISelect<T1, T2>.WhereLike(Expression<Func<T1, T2, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select3Provider<T1, T2, T3> : Select0Provider<ISelect<T1, T2, T3>, T1>, ISelect<T1, T2, T3>
where T1 : class
where T2 : class
where T3 : class {
public Select3Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3));
}
TMember ISelect<T1, T2, T3>.Avg<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.GroupBy(Expression<Func<T1, T2, T3, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3>.Max<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3>.Min<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.OrderBy<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3>.Sum<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3>.ToList<TReturn>(Expression<Func<T1, T2, T3, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.Where(Expression<Func<T1, T2, T3, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereIf(bool condition, Expression<Func<T1, T2, T3, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereLike(Expression<Func<T1, T2, T3, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereLike(Expression<Func<T1, T2, T3, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select4Provider<T1, T2, T3, T4> : Select0Provider<ISelect<T1, T2, T3, T4>, T1>, ISelect<T1, T2, T3, T4>
where T1 : class
where T2 : class
where T3 : class
where T4 : class {
public Select4Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3), typeof(T4));
}
TMember ISelect<T1, T2, T3, T4>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.GroupBy(Expression<Func<T1, T2, T3, T4, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3, T4>.Max<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3, T4>.Min<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3, T4>.Sum<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3, T4>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.Where(Expression<Func<T1, T2, T3, T4, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereLike(Expression<Func<T1, T2, T3, T4, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereLike(Expression<Func<T1, T2, T3, T4, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select5Provider<T1, T2, T3, T4, T5> : Select0Provider<ISelect<T1, T2, T3, T4, T5>, T1>, ISelect<T1, T2, T3, T4, T5>
where T1 : class
where T2 : class
where T3 : class
where T4 : class
where T5 : class {
public Select5Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3), typeof(T4), typeof(T5));
}
TMember ISelect<T1, T2, T3, T4, T5>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3, T4, T5>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5>.Min<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5>.Sum<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3, T4, T5>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.Where(Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select6Provider<T1, T2, T3, T4, T5, T6> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6>, T1>, ISelect<T1, T2, T3, T4, T5, T6>
where T1 : class
where T2 : class
where T3 : class
where T4 : class
where T5 : class
where T6 : class {
public Select6Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6));
}
TMember ISelect<T1, T2, T3, T4, T5, T6>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6>.Min<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6>.Sum<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3, T4, T5, T6>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select7Provider<T1, T2, T3, T4, T5, T6, T7> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7>
where T1 : class
where T2 : class
where T3 : class
where T4 : class
where T5 : class
where T6 : class
where T7 : class {
public Select7Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7));
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7>.Min<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7>.Sum<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract partial class Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8>
where T1 : class
where T2 : class
where T3 : class
where T4 : class
where T5 : class
where T6 : class
where T7 : class
where T8 : class {
public Select8Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8));
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Min<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Sum<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.CommonProvider {
abstract class Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>
where T1 : class
where T2 : class
where T3 : class
where T4 : class
where T5 : class
where T6 : class
where T7 : class
where T8 : class
where T9 : class {
public Select9Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9));
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, object>> columns) => this.InternalGroupBy(columns?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalMax<TMember>(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Min<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalMin<TMember>(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.OrderBy<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalOrderBy(column?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.OrderByDescending<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalOrderByDescending(column?.Body);
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Sum<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalSum<TMember>(column?.Body);
List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, string[]>> columns, string pattern, bool notLike) => this.InternalWhereLikeOr(columns?.Body, pattern, notLike);
ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereLike(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, string>> column, string pattern, bool notLike) => this.InternalWhereLike(column?.Body, pattern, notLike);
}
}

View File

@ -0,0 +1,172 @@
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Internal.CommonProvider {
abstract partial class UpdateProvider<T1> : IUpdate<T1> where T1 : class {
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
protected List<T1> _source = new List<T1>();
protected Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected TableInfo _table;
protected StringBuilder _where = new StringBuilder();
protected StringBuilder _set = new StringBuilder();
protected List<DbParameter> _params = new List<DbParameter>();
protected List<DbParameter> _paramsSource = new List<DbParameter>();
public UpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T1>();
}
public long ExecuteAffrows() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
return _orm.Ado.ExecuteNonQuery(CommandType.Text, sql, _params.Concat(_paramsSource).ToArray());
}
public abstract List<T1> ExecuteUpdated();
public IUpdate<T1> IgnoreColumns(Expression<Func<T1, object>> columns) {
var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false).Distinct();
_ignore.Clear();
foreach (var col in cols) _ignore.Add(col, true);
return this;
}
public IUpdate<T1> SetSource(T1 source) => this.SetSource(new[] { source });
public IUpdate<T1> SetSource(IEnumerable<T1> source) {
if (source == null || source.Any() == false) return this;
_source.AddRange(source.Where(a => a != null));
return this.Where(_source);
}
public IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> column, TMember value) {
var col = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, column?.Body, true);
if (string.IsNullOrEmpty(col)) return this;
_set.Append(", ").Append(col).Append(" = ?p_").Append(_params.Count);
_commonUtils.AppendParamter(_params, null, value);
//foreach (var t in _source) Utils.FillPropertyValue(t, tryf.CsName, value);
return this;
}
public IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> binaryExpression) {
if (binaryExpression?.Body is BinaryExpression == false) return this;
var cols = new List<SelectColumnInfo>();
var expt = _commonExpression.ExpressionWhereLambdaNoneForeignObject(null, cols, binaryExpression);
if (cols.Any() == false) return this;
foreach (var col in cols) {
if (col.Column.Attribute.IsNullable) {
var repltype = col.Column.CsType;
if (repltype.FullName.StartsWith("System.Nullable`1[[System.")) repltype = repltype.GenericTypeArguments[0];
var replval = Activator.CreateInstance(repltype);
if (replval == null) continue;
var replname = _commonUtils.QuoteSqlName(col.Column.Attribute.Name);
replval = _commonUtils.FormatSql("{0}", replval);
expt = expt.Replace(replname, _commonUtils.IsNull(replname, replval));
}
}
_set.Append(", ").Append(_commonUtils.QuoteSqlName(cols.First().Column.Attribute.Name)).Append(" = ").Append(expt);
return this;
}
public IUpdate<T1> SetRaw(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this;
_set.Append(", ").Append(sql);
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this;
}
public IUpdate<T1> Where(Expression<Func<T1, bool>> expression) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, expression?.Body));
public IUpdate<T1> Where(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this;
_where.Append(" AND (").Append(sql).Append(")");
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this;
}
public IUpdate<T1> Where(T1 item) => this.Where(new[] { item });
public IUpdate<T1> Where(IEnumerable<T1> items) => this.Where(_commonUtils.WhereItems(_table, "", items));
public IUpdate<T1> WhereExists<TEntity2>(ISelect<TEntity2> select, bool notExists = false) where TEntity2 : class => this.Where($"{(notExists ? "NOT " : "")}EXISTS({select.ToSql("1")})");
protected abstract void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys);
protected abstract void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d);
public string ToSql() {
if (_where.Length == 0) return null;
var sb = new StringBuilder();
sb.Append("UPDATE ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append(" SET ");
if (_set.Length > 0) { //指定 set 更新
sb.Append(_set.ToString().Substring(2));
} else if (_source.Count == 1) { //保存 Source
_paramsSource.Clear();
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.CsName) == false) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(_commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"));
_commonUtils.AppendParamter(_paramsSource, null, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(_source.First()) : DBNull.Value);
++colidx;
}
}
if (colidx == 0) return null;
} else if (_source.Count > 1) { //批量保存 Source
if (_table.Primarys.Any() == false) return null;
var caseWhen = new StringBuilder();
caseWhen.Append("CASE ");
ToSqlCase(caseWhen, _table.Primarys);
//if (_table.Primarys.Length > 1) caseWhen.Append("CONCAT(");
//var pkidx = 0;
//foreach (var pk in _table.Primarys) {
// if (pkidx > 0) caseWhen.Append(", ");
// caseWhen.Append(_commonUtils.QuoteSqlName(pk.Attribute.Name));
// ++pkidx;
//}
//if (_table.Primarys.Length > 1) caseWhen.Append(")");
var cw = caseWhen.Append(" ").ToString();
_paramsSource.Clear();
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.CsName) == false) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(cw);
foreach (var d in _source) {
sb.Append(" \r\nWHEN ");
ToSqlWhen(sb, _table.Primarys, d);
//if (_table.Primarys.Length > 1) sb.Append("CONCAT(");
//pkidx = 0;
//foreach (var pk in _table.Primarys) {
// if (pkidx > 0) sb.Append(", ");
// sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null));
// ++pkidx;
//}
//if (_table.Primarys.Length > 1) sb.Append(")");
sb.Append(" THEN ").Append(_commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"));
_commonUtils.AppendParamter(_paramsSource, null, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : DBNull.Value);
}
sb.Append(" END");
++colidx;
}
}
if (colidx == 0) return null;
} else
return null;
sb.Append(" \r\nWHERE ").Append(_where.ToString().Substring(5));
return sb.ToString();
}
}
}