mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 04:18:16 +08:00
## v0.9.18
- 增加 PostgreSQL 的 Odbc 访问提供,相比 FreeSql.Provider.PostgreSQL 支持的类型更少; - 增加 通用的 Odbc 访问提供,不能迁移实体到数据库,不能 Skip 这样来分页,理论上能 crud 所有 odbc 数据库;
This commit is contained in:
21
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcDelete.cs
Normal file
21
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcDelete.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using FreeSql.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
class OdbcDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> where T1 : class
|
||||
{
|
||||
public OdbcDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
|
||||
: base(orm, commonUtils, commonExpression, dywhere)
|
||||
{
|
||||
}
|
||||
|
||||
public override List<T1> ExecuteDeleted() => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
public override Task<List<T1>> ExecuteDeletedAsync() => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
}
|
||||
}
|
107
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcInsert.cs
Normal file
107
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcInsert.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using FreeSql.Internal;
|
||||
using SafeObjectPool;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
class OdbcInsert<T1> : Internal.CommonProvider.InsertProvider<T1> where T1 : class
|
||||
{
|
||||
OdbcUtils _utils;
|
||||
public OdbcInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
|
||||
: base(orm, commonUtils, commonExpression)
|
||||
{
|
||||
_utils = _commonUtils as OdbcUtils;
|
||||
}
|
||||
|
||||
public override int ExecuteAffrows() => base.SplitExecuteAffrows(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override long ExecuteIdentity() => base.SplitExecuteIdentity(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override Task<long> ExecuteIdentityAsync() => base.SplitExecuteIdentityAsync(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
|
||||
protected override long RawExecuteIdentity()
|
||||
{
|
||||
var sql = this.ToSql();
|
||||
if (string.IsNullOrEmpty(sql)) return 0;
|
||||
|
||||
Object<DbConnection> poolConn = null;
|
||||
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, string.Concat(sql, $"; {_utils.Adapter.InsertAfterGetIdentitySql}"), _params);
|
||||
_orm.Aop.CurdBefore?.Invoke(this, before);
|
||||
long ret = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
var conn = _connection;
|
||||
if (_transaction != null) conn = _transaction.Connection;
|
||||
if (conn == null)
|
||||
{
|
||||
poolConn = _orm.Ado.MasterPool.Get();
|
||||
conn = poolConn.Value;
|
||||
}
|
||||
_orm.Ado.ExecuteNonQuery(conn, _transaction, CommandType.Text, sql, _params);
|
||||
ret = long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(conn, _transaction, CommandType.Text, _utils.Adapter.InsertAfterGetIdentitySql)), out var trylng) ? trylng : 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (poolConn != null)
|
||||
_orm.Ado.MasterPool.Return(poolConn);
|
||||
|
||||
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
|
||||
_orm.Aop.CurdAfter?.Invoke(this, after);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
async protected override Task<long> RawExecuteIdentityAsync()
|
||||
{
|
||||
var sql = this.ToSql();
|
||||
if (string.IsNullOrEmpty(sql)) return 0;
|
||||
|
||||
Object<DbConnection> poolConn = null;
|
||||
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, string.Concat(sql, $"; {_utils.Adapter.InsertAfterGetIdentitySql}"), _params);
|
||||
_orm.Aop.CurdBefore?.Invoke(this, before);
|
||||
long ret = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
var conn = _connection;
|
||||
if (_transaction != null) conn = _transaction.Connection;
|
||||
if (conn == null)
|
||||
{
|
||||
poolConn = _orm.Ado.MasterPool.Get();
|
||||
conn = poolConn.Value;
|
||||
}
|
||||
await _orm.Ado.ExecuteNonQueryAsync(conn, _transaction, CommandType.Text, sql, _params);
|
||||
ret = long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(conn, _transaction, CommandType.Text, _utils.Adapter.InsertAfterGetIdentitySql)), out var trylng) ? trylng : 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (poolConn != null)
|
||||
_orm.Ado.MasterPool.Return(poolConn);
|
||||
|
||||
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
|
||||
_orm.Aop.CurdAfter?.Invoke(this, after);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected override List<T1> RawExecuteInserted() => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
protected override Task<List<T1>> RawExecuteInsertedAsync() => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
}
|
||||
}
|
189
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcSelect.cs
Normal file
189
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcSelect.cs
Normal file
@ -0,0 +1,189 @@
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
class OdbcSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class
|
||||
{
|
||||
internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, List<Dictionary<Type, string>> tbUnions, List<LambdaExpression> _whereCascadeExpression, IFreeSql _orm)
|
||||
{
|
||||
var _utils = _commonUtils as OdbcUtils;
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure)
|
||||
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
|
||||
|
||||
if (_whereCascadeExpression.Any())
|
||||
foreach (var tb in _tables.Where(a => a.Type != SelectTableInfoType.Parent))
|
||||
tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
var tbUnionsGt0 = tbUnions.Count > 1;
|
||||
for (var tbUnionsIdx = 0; tbUnionsIdx < tbUnions.Count; tbUnionsIdx++)
|
||||
{
|
||||
if (tbUnionsIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n");
|
||||
if (tbUnionsGt0) sb.Append("select * from (");
|
||||
var tbUnion = tbUnions[tbUnionsIdx];
|
||||
|
||||
var sbnav = new StringBuilder();
|
||||
sb.Append(_select);
|
||||
if (_distinct) sb.Append("DISTINCT ");
|
||||
if (_limit > 0 && _utils.Adapter.SelectTopStyle == OdbcAdapter.SelecTopStyle.Top) sb.Append("TOP ").Append(_skip + _limit).Append(" ");
|
||||
sb.Append(field);
|
||||
if (_skip > 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_orderby))
|
||||
{
|
||||
var pktb = _tables.Where(a => a.Table.Primarys.Any()).FirstOrDefault();
|
||||
if (pktb != null) _orderby = string.Concat(" \r\nORDER BY ", pktb.Alias, ".", _commonUtils.QuoteSqlName(pktb?.Table.Primarys.First().Attribute.Name));
|
||||
else _orderby = string.Concat(" \r\nORDER BY ", _tables.First().Alias, ".", _commonUtils.QuoteSqlName(_tables.First().Table.Columns.First().Value.Attribute.Name));
|
||||
}
|
||||
sb.Append(", ROW_NUMBER() OVER(").Append(_orderby).Append(") AS __rownum__");
|
||||
|
||||
throw new NotImplementedException("FreeSql.Odbc.Default 未实现 Skip/Offset 功能,如果需要分页请使用判断上一次 id");
|
||||
}
|
||||
sb.Append(" \r\nFROM ");
|
||||
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
|
||||
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
|
||||
for (var a = 0; a < tbsfrom.Length; a++)
|
||||
{
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(tbsfrom[a].Alias);
|
||||
if (tbsjoin.Length > 0)
|
||||
{
|
||||
//如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1
|
||||
for (var b = 1; b < tbsfrom.Length; b++)
|
||||
{
|
||||
sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(tbsfrom[b].Alias);
|
||||
|
||||
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1");
|
||||
else
|
||||
{
|
||||
sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On);
|
||||
if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")");
|
||||
if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")");
|
||||
if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")");
|
||||
}
|
||||
if (a < tbsfrom.Length - 1) sb.Append(", ");
|
||||
}
|
||||
foreach (var tb in tbsjoin)
|
||||
{
|
||||
if (tb.Type == SelectTableInfoType.Parent) continue;
|
||||
switch (tb.Type)
|
||||
{
|
||||
case SelectTableInfoType.LeftJoin:
|
||||
sb.Append(" \r\nLEFT JOIN ");
|
||||
break;
|
||||
case SelectTableInfoType.InnerJoin:
|
||||
sb.Append(" \r\nINNER JOIN ");
|
||||
break;
|
||||
case SelectTableInfoType.RightJoin:
|
||||
sb.Append(" \r\nRIGHT JOIN ");
|
||||
break;
|
||||
}
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
|
||||
if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")");
|
||||
if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")");
|
||||
}
|
||||
if (_join.Length > 0) sb.Append(_join);
|
||||
|
||||
sbnav.Append(_where);
|
||||
if (!string.IsNullOrEmpty(_tables[0].Cascade))
|
||||
sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")");
|
||||
|
||||
foreach (var tb in _tables)
|
||||
{
|
||||
if (tb.Type == SelectTableInfoType.Parent) continue;
|
||||
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
|
||||
sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
|
||||
}
|
||||
if (sbnav.Length > 0)
|
||||
{
|
||||
sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5));
|
||||
}
|
||||
if (string.IsNullOrEmpty(_groupby) == false)
|
||||
{
|
||||
sb.Append(_groupby);
|
||||
if (string.IsNullOrEmpty(_having) == false)
|
||||
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
|
||||
}
|
||||
if (_skip <= 0)
|
||||
sb.Append(_orderby);
|
||||
else
|
||||
sb.Insert(0, "WITH t AS ( ").Append(" ) SELECT t.* FROM t where __rownum__ > ").Append(_skip);
|
||||
|
||||
sbnav.Clear();
|
||||
if (_limit > 0 && _utils.Adapter.SelectTopStyle == OdbcAdapter.SelecTopStyle.Limit) sb.Append(" \r\nLIMIT ").Append(_skip + _limit);
|
||||
if (tbUnionsGt0) sb.Append(") ftb");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override 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) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override 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) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override 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) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override 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) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override 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) { this.InternalFrom(exp); var ret = new OdbcSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); OdbcSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class
|
||||
{
|
||||
public OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class
|
||||
{
|
||||
public OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class
|
||||
{
|
||||
public OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class
|
||||
{
|
||||
public OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<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 OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<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 OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<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 OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<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 OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
class OdbcSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<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 OdbcSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||
public override string ToSql(string field = null) => OdbcSelect<T1>.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _whereCascadeExpression, _orm);
|
||||
}
|
||||
}
|
64
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcUpdate.cs
Normal file
64
Providers/FreeSql.Provider.Odbc/Default/Curd/OdbcUpdate.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
class OdbcUpdate<T1> : Internal.CommonProvider.UpdateProvider<T1> where T1 : class
|
||||
{
|
||||
OdbcUtils _utils;
|
||||
public OdbcUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
|
||||
: base(orm, commonUtils, commonExpression, dywhere)
|
||||
{
|
||||
_utils = _commonUtils as OdbcUtils;
|
||||
}
|
||||
|
||||
public override int ExecuteAffrows() => base.SplitExecuteAffrows(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(_utils.Adapter.InsertBatchSplitLimit, 255);
|
||||
|
||||
protected override List<T1> RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
protected override Task<List<T1>> RawExecuteUpdatedAsync() => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
|
||||
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys)
|
||||
{
|
||||
if (_table.Primarys.Length == 1)
|
||||
{
|
||||
caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
|
||||
return;
|
||||
}
|
||||
caseWhen.Append("(");
|
||||
var pkidx = 0;
|
||||
foreach (var pk in _table.Primarys)
|
||||
{
|
||||
if (pkidx > 0) caseWhen.Append(", ");
|
||||
caseWhen.Append(_utils.Adapter.CastSql(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)), _utils.Adapter.MappingOdbcTypeVarChar));
|
||||
++pkidx;
|
||||
}
|
||||
caseWhen.Append(")");
|
||||
}
|
||||
|
||||
protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d)
|
||||
{
|
||||
if (_table.Primarys.Length == 1)
|
||||
{
|
||||
sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
|
||||
return;
|
||||
}
|
||||
var pkidx = 0;
|
||||
foreach (var pk in _table.Primarys)
|
||||
{
|
||||
if (pkidx > 0) sb.Append(", ");
|
||||
sb.Append(_utils.Adapter.CastSql(_commonUtils.FormatSql("{0}", pk.GetMapValue(d)), _utils.Adapter.MappingOdbcTypeVarChar));
|
||||
++pkidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
173
Providers/FreeSql.Provider.Odbc/Default/OdbcAdapter.cs
Normal file
173
Providers/FreeSql.Provider.Odbc/Default/OdbcAdapter.cs
Normal file
@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
public class OdbcAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Select TOP 1,或 Limit 1 风格
|
||||
/// </summary>
|
||||
public virtual SelecTopStyle SelectTopStyle => SelecTopStyle.Top;
|
||||
public enum SelecTopStyle { Top, Limit }
|
||||
|
||||
/// <summary>
|
||||
/// 插入成功后,获取自增值
|
||||
/// </summary>
|
||||
public virtual string InsertAfterGetIdentitySql => "SELECT SCOPE_IDENTITY()";
|
||||
/// <summary>
|
||||
/// 批量插入时,自动拆分的每次执行数量
|
||||
/// </summary>
|
||||
public virtual int InsertBatchSplitLimit => 255;
|
||||
/// <summary>
|
||||
/// 批量更新时,自动拆分的每次执行数量
|
||||
/// </summary>
|
||||
public virtual int UpdateBatchSplitLimit => 255;
|
||||
|
||||
public virtual string MappingOdbcTypeBit => "int";
|
||||
public virtual string MappingOdbcTypeSmallInt => "smallint";
|
||||
public virtual string MappingOdbcTypeInt => "int";
|
||||
public virtual string MappingOdbcTypeBigInt => "bigint";
|
||||
public virtual string MappingOdbcTypeTinyInt => "tinyint";
|
||||
public virtual string MappingOdbcTypeDecimal => "decimal";
|
||||
public virtual string MappingOdbcTypeDouble => "float";
|
||||
public virtual string MappingOdbcTypeReal => "real";
|
||||
public virtual string MappingOdbcTypeDateTime => "datetime";
|
||||
public virtual string MappingOdbcTypeVarBinary => "varbinary";
|
||||
public virtual string MappingOdbcTypeVarChar => "nvarchar";
|
||||
public virtual string MappingOdbcTypeText => "nvarchar(max)";
|
||||
public virtual string MappingOdbcTypeUniqueIdentifier => "uniqueidentifier";
|
||||
|
||||
public virtual char QuoteSqlNameLeft => '[';
|
||||
public virtual char QuoteSqlNameRight => ']';
|
||||
|
||||
public virtual string FieldSql(Type type, string columnName) => columnName;
|
||||
public virtual string UnicodeStringRawSql(object value) => value == null ? "NULL" : string.Concat("N'", value.ToString().Replace("'", "''"), "'");
|
||||
public virtual string DateTimeRawSql(object value)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
if (value.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
|
||||
return string.Concat("'", ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss"), "'");
|
||||
}
|
||||
public virtual string TimeSpanRawSql(object value) => value == null ? "NULL" : ((TimeSpan)value).TotalSeconds.ToString();
|
||||
public virtual string ByteRawSql(object value)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
var bytes = value as byte[];
|
||||
var sb = new StringBuilder().Append("0x");
|
||||
foreach (var vc in bytes)
|
||||
{
|
||||
if (vc < 10) sb.Append("0");
|
||||
sb.Append(vc.ToString("X"));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public virtual string CastSql(string sql, string to) => $"cast({sql} as {to})";
|
||||
public virtual string IsNullSql(string sql, object value) => $"isnull({sql}, {value})";
|
||||
public virtual string ConcatSql(string[] objs, Type[] types)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var news = new string[objs.Length];
|
||||
for (var a = 0; a < objs.Length; a++)
|
||||
news[a] = types[a] == typeof(string) ? objs[a] : $"cast({objs[a]} as nvarchar)";
|
||||
return string.Join(" + ", news);
|
||||
}
|
||||
|
||||
public virtual string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}";
|
||||
public virtual string Div(string left, string right, Type leftType, Type rightType) => $"{left} / {right}";
|
||||
|
||||
public virtual string LambdaConvert_ToBoolean(Type type, string operand) => $"(cast({operand} as varchar) not in ('0','false'))";
|
||||
public virtual string LambdaConvert_ToByte(Type type, string operand) => $"cast({operand} as tinyint)";
|
||||
public virtual string LambdaConvert_ToChar(Type type, string operand) => $"substring(cast({operand} as varchar),1,1)";
|
||||
public virtual string LambdaConvert_ToDateTime(Type type, string operand) => $"cast({operand} as datetime)";
|
||||
public virtual string LambdaConvert_ToDecimal(Type type, string operand) => $"cast({operand} as decimal(36,18))";
|
||||
public virtual string LambdaConvert_ToDouble(Type type, string operand) => $"cast({operand} as decimal(32,16))";
|
||||
public virtual string LambdaConvert_ToInt16(Type type, string operand) => $"cast({operand} as smallint)";
|
||||
public virtual string LambdaConvert_ToInt32(Type type, string operand) => $"cast({operand} as int)";
|
||||
public virtual string LambdaConvert_ToInt64(Type type, string operand) => $"cast({operand} as bigint)";
|
||||
public virtual string LambdaConvert_ToSByte(Type type, string operand) => $"cast({operand} as tinyint)";
|
||||
public virtual string LambdaConvert_ToSingle(Type type, string operand) => $"cast({operand} as decimal(14,7))";
|
||||
public virtual string LambdaConvert_ToString(Type type, string operand) => type.NullableTypeOrThis() == typeof(Guid) ? $"cast({operand} as varchar(36))" : $"cast({operand} as nvarchar)";
|
||||
public virtual string LambdaConvert_ToUInt16(Type type, string operand) => $"cast({operand} as smallint)";
|
||||
public virtual string LambdaConvert_ToUInt32(Type type, string operand) => $"cast({operand} as int)";
|
||||
public virtual string LambdaConvert_ToUInt64(Type type, string operand) => $"cast({operand} as bigint)";
|
||||
public virtual string LambdaConvert_ToGuid(Type type, string operand) => $"cast({operand} as uniqueidentifier)";
|
||||
|
||||
public virtual string LambdaGuid_NewGuid => "newid()";
|
||||
public virtual string LambdaRandom_Next => "cast(rand()*1000000000 as int)";
|
||||
public virtual string LambdaRandom_NextDouble => "rand()";
|
||||
|
||||
public virtual string LambdaString_IsNullOrEmpty(string operand) => $"({operand} is null or {operand} = '')";
|
||||
public virtual string LambdaString_IsNullOrWhiteSpace(string operand) => $"({operand} is null or {operand} = '' or ltrim({operand}) = '')";
|
||||
public virtual string LambdaString_Length(string operand) => $"len({operand})";
|
||||
|
||||
public virtual string LambdaString_ToLower(string operand) => $"lower({operand})";
|
||||
public virtual string LambdaString_ToUpper(string operand) => $"upper({operand})";
|
||||
public virtual string LambdaString_Substring(string operand, string startIndex, string length) => string.IsNullOrEmpty(length) ? $"left({operand}, {startIndex})" : $"substring({operand}, {startIndex}, {length})";
|
||||
public virtual string LambdaString_IndexOf(string operand, string value, string startIndex) => string.IsNullOrEmpty(startIndex) ? $"(charindex({operand}, {value})-1)" : $"(charindex({operand}, {value}, {startIndex})-1)";
|
||||
public virtual string LambdaString_PadLeft(string operand, string length, string paddingChar) => string.IsNullOrEmpty(paddingChar) ? $"lpad({operand}, {length})" : $"lpad({operand}, {length}, {paddingChar})";
|
||||
public virtual string LambdaString_PadRight(string operand, string length, string paddingChar) => string.IsNullOrEmpty(paddingChar) ? $"rpad({operand}, {length})" : $"rpad({operand}, {length}, {paddingChar})";
|
||||
public virtual string LambdaString_Trim(string operand) => $"ltrim(rtrim({operand}))";
|
||||
public virtual string LambdaString_TrimStart(string operand) => $"ltrim({operand})";
|
||||
public virtual string LambdaString_TrimEnd(string operand) => $"rtrim({operand})";
|
||||
public virtual string LambdaString_Replace(string operand, string oldValue, string newValue) => $"replace({operand}, {oldValue}, {newValue})";
|
||||
public virtual string LambdaString_CompareTo(string operand, string value) => $"({operand} - {value})";
|
||||
public virtual string LambdaString_Equals(string operand, string value) => $"({operand} = {value})";
|
||||
|
||||
public virtual string LambdaDateTime_Now => "getdate()";
|
||||
public virtual string LambdaDateTime_UtcNow => "getutcdate()";
|
||||
public virtual string LambdaDateTime_Today => "convert(char(10),getdate(),120)";
|
||||
public virtual string LambdaDateTime_MinValue => "'1753/1/1 0:00:00'";
|
||||
public virtual string LambdaDateTime_MaxValue => "'9999/12/31 23:59:59'";
|
||||
public virtual string LambdaDateTime_Date(string operand) => $"convert(char(10),{operand},120)";
|
||||
public virtual string LambdaDateTime_TimeOfDay(string operand) => $"datediff(second, convert(char(10),{operand},120), {operand})";
|
||||
public virtual string LambdaDateTime_DayOfWeek(string operand) => $"(datepart(weekday, {operand})-1)";
|
||||
public virtual string LambdaDateTime_Day(string operand) => $"datepart(day, {operand})";
|
||||
public virtual string LambdaDateTime_DayOfYear(string operand) => $"datepart(dayofyear, {operand})";
|
||||
public virtual string LambdaDateTime_Month(string operand) => $"datepart(month, {operand})";
|
||||
public virtual string LambdaDateTime_Year(string operand) => $"datepart(year, {operand})";
|
||||
public virtual string LambdaDateTime_Hour(string operand) => $"datepart(hour, {operand})";
|
||||
public virtual string LambdaDateTime_Minute(string operand) => $"datepart(minute, {operand})";
|
||||
public virtual string LambdaDateTime_Second(string operand) => $"datepart(second, {operand})";
|
||||
public virtual string LambdaDateTime_Millisecond(string operand) => $"(datepart(millisecond, {operand})/1000)";
|
||||
public virtual string LambdaDateTime_Ticks(string operand) => $"(cast(datediff(second, '1970-1-1', {operand}) as bigint)*10000000+621355968000000000)";
|
||||
|
||||
public virtual string LambdaDateTime_DaysInMonth(string year, string month) => $"datepart(day, dateadd(day, -1, dateadd(month, 1, cast({year} as varchar) + '-' + cast({month} as varchar) + '-1')))";
|
||||
public virtual string LambdaDateTime_IsLeapYear(string year) => $"(({year})%4=0 AND ({year})%100<>0 OR ({year})%400=0)";
|
||||
public virtual string LambdaDateTime_Add(string operand, string value) => $"dateadd(second, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_AddDays(string operand, string value) => $"dateadd(day, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_AddHours(string operand, string value) => $"dateadd(hour, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_AddMilliseconds(string operand, string value) => $"dateadd(second, ({value})/1000, {operand})";
|
||||
public virtual string LambdaDateTime_AddMinutes(string operand, string value) => $"dateadd(minute, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_AddMonths(string operand, string value) => $"dateadd(month, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_AddSeconds(string operand, string value) => $"dateadd(second, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_AddTicks(string operand, string value) => $"dateadd(second, ({value})/10000000, {operand})";
|
||||
public virtual string LambdaDateTime_AddYears(string operand, string value) => $"dateadd(year, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_Subtract(string operand, string value) => $"datediff(second, {value}, {operand})";
|
||||
public virtual string LambdaDateTime_SubtractTimeSpan(string operand, string value) => $"dateadd(second, ({value})*-1, {operand})";
|
||||
public virtual string LambdaDateTime_Equals(string operand, string value) => $"({operand} = {value})";
|
||||
public virtual string LambdaDateTime_CompareTo(string operand, string value) => $"datediff(second,{value},{operand})";
|
||||
public virtual string LambdaDateTime_ToString(string operand) => $"convert(varchar, {operand}, 121)";
|
||||
|
||||
public virtual string LambdaMath_Abs(string operand) => $"abs({operand})";
|
||||
public virtual string LambdaMath_Sign(string operand) => $"sign({operand})";
|
||||
public virtual string LambdaMath_Floor(string operand) => $"floor({operand})";
|
||||
public virtual string LambdaMath_Ceiling(string operand) => $"ceiling({ operand})";
|
||||
public virtual string LambdaMath_Round(string operand, string decimals) => $"round({operand}, {decimals})";
|
||||
public virtual string LambdaMath_Exp(string operand) => $"exp({operand})";
|
||||
public virtual string LambdaMath_Log(string operand) => $"log({operand})";
|
||||
public virtual string LambdaMath_Log10(string operand) => $"log10({operand})";
|
||||
public virtual string LambdaMath_Pow(string operand, string y) => $"power({operand}, {y})";
|
||||
public virtual string LambdaMath_Sqrt(string operand) => $"sqrt({operand})";
|
||||
public virtual string LambdaMath_Cos(string operand) => $"cos({operand})";
|
||||
public virtual string LambdaMath_Sin(string operand) => $"sin({operand})";
|
||||
public virtual string LambdaMath_Tan(string operand) => $"tan({operand})";
|
||||
public virtual string LambdaMath_Acos(string operand) => $"acos({operand})";
|
||||
public virtual string LambdaMath_Asin(string operand) => $"asin({operand})";
|
||||
public virtual string LambdaMath_Atan(string operand) => $"atan({operand})";
|
||||
public virtual string LambdaMath_Atan2(string operand, string x) => $"atan2({operand}, {x})";
|
||||
public virtual string LambdaMath_Truncate(string operand) => $"floor({operand})";
|
||||
}
|
||||
}
|
73
Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs
Normal file
73
Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using FreeSql.Internal;
|
||||
using SafeObjectPool;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Data.Common;
|
||||
using System.Data.Odbc;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
class OdbcAdo : FreeSql.Internal.CommonProvider.AdoProvider
|
||||
{
|
||||
public OdbcAdo() : base(DataType.Odbc) { }
|
||||
public OdbcAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.Odbc)
|
||||
{
|
||||
base._util = util;
|
||||
if (!string.IsNullOrEmpty(masterConnectionString))
|
||||
MasterPool = new OdbcConnectionPool("主库", masterConnectionString, null, null);
|
||||
if (slaveConnectionStrings != null)
|
||||
{
|
||||
foreach (var slaveConnectionString in slaveConnectionStrings)
|
||||
{
|
||||
var slavePool = new OdbcConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables));
|
||||
SlavePools.Add(slavePool);
|
||||
}
|
||||
}
|
||||
}
|
||||
OdbcAdapter Adapter => (_util == null ? FreeSqlOdbcGlobalExtensions.DefaultOdbcAdapter : _util._orm.GetOdbcAdapter());
|
||||
|
||||
static DateTime dt1970 = new DateTime(1970, 1, 1);
|
||||
public override object AddslashesProcessParam(object param, Type mapType)
|
||||
{
|
||||
if (param == null) return "NULL";
|
||||
if (mapType != null && mapType != param.GetType())
|
||||
param = Utils.GetDataReaderValue(mapType, param);
|
||||
if (param is bool || param is bool?)
|
||||
return (bool)param ? 1 : 0;
|
||||
else if (param is string)
|
||||
return Adapter.UnicodeStringRawSql(param);
|
||||
else if (param is char)
|
||||
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
|
||||
else if (param is Enum)
|
||||
return ((Enum)param).ToInt64();
|
||||
else if (decimal.TryParse(string.Concat(param), out var trydec))
|
||||
return param;
|
||||
else if (param is DateTime || param is DateTime?)
|
||||
return Adapter.DateTimeRawSql(param);
|
||||
else if (param is TimeSpan || param is TimeSpan?)
|
||||
return Adapter.TimeSpanRawSql(param);
|
||||
else if (param is IEnumerable)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var ie = param as IEnumerable;
|
||||
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
|
||||
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
|
||||
}
|
||||
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
|
||||
}
|
||||
|
||||
protected override DbCommand CreateCommand()
|
||||
{
|
||||
return new OdbcCommand();
|
||||
}
|
||||
|
||||
protected override void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex)
|
||||
{
|
||||
(pool as OdbcConnectionPool).Return(conn, ex);
|
||||
}
|
||||
|
||||
protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj);
|
||||
}
|
||||
}
|
@ -0,0 +1,236 @@
|
||||
using SafeObjectPool;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.Odbc;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
class OdbcConnectionPool : ObjectPool<DbConnection>
|
||||
{
|
||||
|
||||
internal Action availableHandler;
|
||||
internal Action unavailableHandler;
|
||||
|
||||
public OdbcConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null)
|
||||
{
|
||||
var policy = new OdbcConnectionPoolPolicy
|
||||
{
|
||||
_pool = this,
|
||||
Name = name
|
||||
};
|
||||
this.Policy = policy;
|
||||
policy.ConnectionString = connectionString;
|
||||
|
||||
this.availableHandler = availableHandler;
|
||||
this.unavailableHandler = unavailableHandler;
|
||||
}
|
||||
|
||||
public void Return(Object<DbConnection> obj, Exception exception, bool isRecreate = false)
|
||||
{
|
||||
if (exception != null && exception is OdbcException)
|
||||
{
|
||||
|
||||
if (obj.Value.Ping() == false)
|
||||
{
|
||||
|
||||
base.SetUnavailable(exception);
|
||||
}
|
||||
}
|
||||
base.Return(obj, isRecreate);
|
||||
}
|
||||
}
|
||||
|
||||
class OdbcConnectionPoolPolicy : IPolicy<DbConnection>
|
||||
{
|
||||
|
||||
internal OdbcConnectionPool _pool;
|
||||
public string Name { get; set; } = "Default OdbcConnection 对象池";
|
||||
public int PoolSize { get; set; } = 100;
|
||||
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
||||
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
|
||||
public int AsyncGetCapacity { get; set; } = 10000;
|
||||
public bool IsThrowGetTimeoutException { get; set; } = true;
|
||||
public int CheckAvailableInterval { get; set; } = 5;
|
||||
|
||||
static ConcurrentDictionary<string, int> dicConnStrIncr = new ConcurrentDictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
|
||||
private string _connectionString;
|
||||
public string ConnectionString
|
||||
{
|
||||
get => _connectionString;
|
||||
set
|
||||
{
|
||||
_connectionString = value ?? "";
|
||||
|
||||
var pattern = @"Max\s*pool\s*size\s*=\s*(\d+)";
|
||||
Match m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
|
||||
if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
|
||||
var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
|
||||
PoolSize = poolsize + connStrIncr;
|
||||
_connectionString = m.Success ?
|
||||
Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
|
||||
$"{_connectionString};Max pool size={PoolSize}";
|
||||
|
||||
pattern = @"Connection\s*LifeTime\s*=\s*(\d+)";
|
||||
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
|
||||
if (m.Success)
|
||||
{
|
||||
IdleTimeout = TimeSpan.FromSeconds(int.Parse(m.Groups[1].Value));
|
||||
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
var minPoolSize = 0;
|
||||
pattern = @"Min\s*pool\s*size\s*=\s*(\d+)";
|
||||
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
|
||||
if (m.Success)
|
||||
{
|
||||
minPoolSize = int.Parse(m.Groups[1].Value);
|
||||
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
FreeSql.Internal.CommonUtils.PrevReheatConnectionPool(_pool, minPoolSize);
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnCheckAvailable(Object<DbConnection> obj)
|
||||
{
|
||||
if (obj.Value.State == ConnectionState.Closed) obj.Value.Open();
|
||||
return obj.Value.Ping(true);
|
||||
}
|
||||
|
||||
public DbConnection OnCreate()
|
||||
{
|
||||
var conn = new OdbcConnection(_connectionString);
|
||||
return conn;
|
||||
}
|
||||
|
||||
public void OnDestroy(DbConnection obj)
|
||||
{
|
||||
if (obj.State != ConnectionState.Closed) obj.Close();
|
||||
obj.Dispose();
|
||||
}
|
||||
|
||||
public void OnGet(Object<DbConnection> obj)
|
||||
{
|
||||
|
||||
if (_pool.IsAvailable)
|
||||
{
|
||||
|
||||
if (obj.Value == null)
|
||||
{
|
||||
if (_pool.SetUnavailable(new Exception("连接字符串错误")) == true)
|
||||
throw new Exception($"【{this.Name}】连接字符串错误,请检查。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
obj.Value.Open();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (_pool.SetUnavailable(ex) == true)
|
||||
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async public Task OnGetAsync(Object<DbConnection> obj)
|
||||
{
|
||||
|
||||
if (_pool.IsAvailable)
|
||||
{
|
||||
|
||||
if (obj.Value == null)
|
||||
{
|
||||
if (_pool.SetUnavailable(new Exception("连接字符串错误")) == true)
|
||||
throw new Exception($"【{this.Name}】连接字符串错误,请检查。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && (await obj.Value.PingAsync()) == false)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
await obj.Value.OpenAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (_pool.SetUnavailable(ex) == true)
|
||||
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnGetTimeout()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnReturn(Object<DbConnection> obj)
|
||||
{
|
||||
if (obj.Value.State != ConnectionState.Closed) try { obj.Value.Close(); } catch { }
|
||||
}
|
||||
|
||||
public void OnAvailable()
|
||||
{
|
||||
_pool.availableHandler?.Invoke();
|
||||
}
|
||||
|
||||
public void OnUnavailable()
|
||||
{
|
||||
_pool.unavailableHandler?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
static class DbConnectionExtensions
|
||||
{
|
||||
|
||||
static DbCommand PingCommand(DbConnection conn)
|
||||
{
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandTimeout = 5;
|
||||
cmd.CommandText = "select 1";
|
||||
return cmd;
|
||||
}
|
||||
public static bool Ping(this DbConnection that, bool isThrow = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
PingCommand(that).ExecuteNonQuery();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
|
||||
if (isThrow) throw;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async public static Task<bool> PingAsync(this DbConnection that, bool isThrow = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PingCommand(that).ExecuteNonQueryAsync();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
|
||||
if (isThrow) throw;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
90
Providers/FreeSql.Provider.Odbc/Default/OdbcCodeFirst.cs
Normal file
90
Providers/FreeSql.Provider.Odbc/Default/OdbcCodeFirst.cs
Normal file
@ -0,0 +1,90 @@
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Odbc;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
class OdbcCodeFirst : Internal.CommonProvider.CodeFirstProvider
|
||||
{
|
||||
public override bool IsAutoSyncStructure { get => false; set => base.IsAutoSyncStructure = false; }
|
||||
public override bool IsNoneCommandParameter { get => true; set => base.IsNoneCommandParameter = true; }
|
||||
public OdbcCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression)
|
||||
{
|
||||
_utils = _commonUtils as OdbcUtils;
|
||||
}
|
||||
|
||||
OdbcUtils _utils;
|
||||
object _dicCsToDbLock = new object();
|
||||
Dictionary<string, (OdbcType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb;
|
||||
|
||||
public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type)
|
||||
{
|
||||
if (_dicCsToDb == null)
|
||||
{
|
||||
lock (_dicCsToDbLock)
|
||||
{
|
||||
if (_dicCsToDb == null)
|
||||
{
|
||||
var reg = new Regex(@"\([^\)]+\)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
Func<string, string> deleteBrackets = str => reg.Replace(str, "");
|
||||
|
||||
_dicCsToDb = new Dictionary<string, (OdbcType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() {
|
||||
{ typeof(bool).FullName, (OdbcType.Bit, _utils.Adapter.MappingOdbcTypeBit,$"{_utils.Adapter.MappingOdbcTypeBit} NOT NULL", null, false, false) },{ typeof(bool?).FullName, (OdbcType.Bit, _utils.Adapter.MappingOdbcTypeBit,_utils.Adapter.MappingOdbcTypeBit, null, true, null) },
|
||||
|
||||
{ typeof(sbyte).FullName, (OdbcType.SmallInt, _utils.Adapter.MappingOdbcTypeSmallInt, $"{_utils.Adapter.MappingOdbcTypeSmallInt} NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, (OdbcType.SmallInt, _utils.Adapter.MappingOdbcTypeSmallInt, _utils.Adapter.MappingOdbcTypeSmallInt, false, true, null) },
|
||||
{ typeof(short).FullName, (OdbcType.SmallInt, _utils.Adapter.MappingOdbcTypeSmallInt,$"{_utils.Adapter.MappingOdbcTypeSmallInt} NOT NULL", false, false, 0) },{ typeof(short?).FullName, (OdbcType.SmallInt, _utils.Adapter.MappingOdbcTypeSmallInt, _utils.Adapter.MappingOdbcTypeSmallInt, false, true, null) },
|
||||
{ typeof(int).FullName, (OdbcType.Int, _utils.Adapter.MappingOdbcTypeInt, $"{_utils.Adapter.MappingOdbcTypeInt} NOT NULL", false, false, 0) },{ typeof(int?).FullName, (OdbcType.Int, _utils.Adapter.MappingOdbcTypeInt, _utils.Adapter.MappingOdbcTypeInt, false, true, null) },
|
||||
{ typeof(long).FullName, (OdbcType.BigInt, _utils.Adapter.MappingOdbcTypeBigInt,$"{_utils.Adapter.MappingOdbcTypeBigInt} NOT NULL", false, false, 0) },{ typeof(long?).FullName, (OdbcType.BigInt, _utils.Adapter.MappingOdbcTypeBigInt,_utils.Adapter.MappingOdbcTypeBigInt, false, true, null) },
|
||||
|
||||
{ typeof(byte).FullName, (OdbcType.TinyInt, _utils.Adapter.MappingOdbcTypeTinyInt,$"{_utils.Adapter.MappingOdbcTypeTinyInt} NOT NULL", true, false, 0) },{ typeof(byte?).FullName, (OdbcType.TinyInt, _utils.Adapter.MappingOdbcTypeTinyInt,_utils.Adapter.MappingOdbcTypeTinyInt, true, true, null) },
|
||||
{ typeof(ushort).FullName, (OdbcType.Int, _utils.Adapter.MappingOdbcTypeInt,$"{_utils.Adapter.MappingOdbcTypeInt} NOT NULL", true, false, 0) },{ typeof(ushort?).FullName, (OdbcType.Int, _utils.Adapter.MappingOdbcTypeInt, _utils.Adapter.MappingOdbcTypeInt, true, true, null) },
|
||||
{ typeof(uint).FullName, (OdbcType.BigInt, _utils.Adapter.MappingOdbcTypeBigInt, $"{_utils.Adapter.MappingOdbcTypeBigInt} NOT NULL", true, false, 0) },{ typeof(uint?).FullName, (OdbcType.BigInt, _utils.Adapter.MappingOdbcTypeBigInt, _utils.Adapter.MappingOdbcTypeBigInt, true, true, null) },
|
||||
{ typeof(ulong).FullName, (OdbcType.Decimal, _utils.Adapter.MappingOdbcTypeDecimal, $"{_utils.Adapter.MappingOdbcTypeDecimal}(20,0) NOT NULL", true, false, 0) },{ typeof(ulong?).FullName, (OdbcType.Decimal, _utils.Adapter.MappingOdbcTypeDecimal, $"{_utils.Adapter.MappingOdbcTypeDecimal}(20,0)", true, true, null) },
|
||||
|
||||
{ typeof(double).FullName, (OdbcType.Double, _utils.Adapter.MappingOdbcTypeDouble, $"{_utils.Adapter.MappingOdbcTypeDouble} NOT NULL", false, false, 0) },{ typeof(double?).FullName, (OdbcType.Double, _utils.Adapter.MappingOdbcTypeDouble, _utils.Adapter.MappingOdbcTypeDouble, false, true, null) },
|
||||
{ typeof(float).FullName, (OdbcType.Real, _utils.Adapter.MappingOdbcTypeReal,$"{_utils.Adapter.MappingOdbcTypeReal} NOT NULL", false, false, 0) },{ typeof(float?).FullName, (OdbcType.Real, _utils.Adapter.MappingOdbcTypeReal,_utils.Adapter.MappingOdbcTypeReal, false, true, null) },
|
||||
{ typeof(decimal).FullName, (OdbcType.Decimal, _utils.Adapter.MappingOdbcTypeDecimal, $"{_utils.Adapter.MappingOdbcTypeDecimal}(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, (OdbcType.Decimal, _utils.Adapter.MappingOdbcTypeDecimal, $"{_utils.Adapter.MappingOdbcTypeDecimal}(10,2)", false, true, null) },
|
||||
|
||||
{ typeof(DateTime).FullName, (OdbcType.DateTime, _utils.Adapter.MappingOdbcTypeDateTime, $"{_utils.Adapter.MappingOdbcTypeDateTime} NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (OdbcType.DateTime, _utils.Adapter.MappingOdbcTypeDateTime, _utils.Adapter.MappingOdbcTypeDateTime, false, true, null) },
|
||||
|
||||
{ typeof(byte[]).FullName, (OdbcType.VarBinary, _utils.Adapter.MappingOdbcTypeVarBinary, $"{_utils.Adapter.MappingOdbcTypeVarBinary}(255)", false, null, new byte[0]) },
|
||||
{ typeof(string).FullName, (OdbcType.VarChar, _utils.Adapter.MappingOdbcTypeVarChar, $"{_utils.Adapter.MappingOdbcTypeVarChar}(255)", false, null, "") },
|
||||
|
||||
{ typeof(Guid).FullName, (OdbcType.UniqueIdentifier, deleteBrackets(_utils.Adapter.MappingOdbcTypeUniqueIdentifier), $"{_utils.Adapter.MappingOdbcTypeUniqueIdentifier} NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (OdbcType.UniqueIdentifier, deleteBrackets(_utils.Adapter.MappingOdbcTypeUniqueIdentifier), _utils.Adapter.MappingOdbcTypeUniqueIdentifier, false, true, null) },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue));
|
||||
if (type.IsArray) return null;
|
||||
var enumType = type.IsEnum ? type : null;
|
||||
if (enumType == null && type.IsNullableType() && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
|
||||
if (enumType != null)
|
||||
{
|
||||
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
|
||||
(OdbcType.BigInt, _utils.Adapter.MappingOdbcTypeBigInt, $"{_utils.Adapter.MappingOdbcTypeBigInt}{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) :
|
||||
(OdbcType.Int, _utils.Adapter.MappingOdbcTypeInt, $"{_utils.Adapter.MappingOdbcTypeInt}{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0));
|
||||
if (_dicCsToDb.ContainsKey(type.FullName) == false)
|
||||
{
|
||||
lock (_dicCsToDbLock)
|
||||
{
|
||||
if (_dicCsToDb.ContainsKey(type.FullName) == false)
|
||||
_dicCsToDb.Add(type.FullName, newItem);
|
||||
}
|
||||
}
|
||||
return ((int)newItem.Item1, newItem.Item2, newItem.Item3, newItem.Item5, newItem.Item6);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string GetComparisonDDLStatements(params Type[] entityTypes) => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
}
|
||||
}
|
441
Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs
Normal file
441
Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs
Normal file
@ -0,0 +1,441 @@
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
class OdbcExpression : CommonExpression
|
||||
{
|
||||
OdbcUtils _utils;
|
||||
public OdbcExpression(CommonUtils common) : base(common)
|
||||
{
|
||||
_utils = common as OdbcUtils;
|
||||
}
|
||||
|
||||
public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc)
|
||||
{
|
||||
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.Convert:
|
||||
var operandExp = (exp as UnaryExpression)?.Operand;
|
||||
var gentype = exp.Type.NullableTypeOrThis();
|
||||
if (gentype != operandExp.Type.NullableTypeOrThis())
|
||||
{
|
||||
switch (gentype.ToString())
|
||||
{
|
||||
case "System.Boolean": return _utils.Adapter.LambdaConvert_ToBoolean(operandExp.Type, getExp(operandExp));
|
||||
case "System.Byte": return _utils.Adapter.LambdaConvert_ToByte(operandExp.Type, getExp(operandExp));
|
||||
case "System.Char": return _utils.Adapter.LambdaConvert_ToChar(operandExp.Type, getExp(operandExp));
|
||||
case "System.DateTime": return _utils.Adapter.LambdaConvert_ToDateTime(operandExp.Type, getExp(operandExp));
|
||||
case "System.Decimal": return _utils.Adapter.LambdaConvert_ToDecimal(operandExp.Type, getExp(operandExp));
|
||||
case "System.Double": return _utils.Adapter.LambdaConvert_ToDouble(operandExp.Type, getExp(operandExp));
|
||||
case "System.Int16": return _utils.Adapter.LambdaConvert_ToInt16(operandExp.Type, getExp(operandExp));
|
||||
case "System.Int32": return _utils.Adapter.LambdaConvert_ToInt32(operandExp.Type, getExp(operandExp));
|
||||
case "System.Int64": return _utils.Adapter.LambdaConvert_ToInt64(operandExp.Type, getExp(operandExp));
|
||||
case "System.SByte": return _utils.Adapter.LambdaConvert_ToSByte(operandExp.Type, getExp(operandExp));
|
||||
case "System.Single": return _utils.Adapter.LambdaConvert_ToSingle(operandExp.Type, getExp(operandExp));
|
||||
case "System.String": return _utils.Adapter.LambdaConvert_ToString(operandExp.Type, getExp(operandExp));
|
||||
case "System.UInt16": return _utils.Adapter.LambdaConvert_ToUInt16(operandExp.Type, getExp(operandExp));
|
||||
case "System.UInt32": return _utils.Adapter.LambdaConvert_ToUInt32(operandExp.Type, getExp(operandExp));
|
||||
case "System.UInt64": return _utils.Adapter.LambdaConvert_ToUInt64(operandExp.Type, getExp(operandExp));
|
||||
case "System.Guid": return _utils.Adapter.LambdaConvert_ToGuid(operandExp.Type, getExp(operandExp));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExpressionType.Call:
|
||||
var callExp = exp as MethodCallExpression;
|
||||
|
||||
switch (callExp.Method.Name)
|
||||
{
|
||||
case "Parse":
|
||||
case "TryParse":
|
||||
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString())
|
||||
{
|
||||
case "System.Boolean": return _utils.Adapter.LambdaConvert_ToBoolean(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Byte": return _utils.Adapter.LambdaConvert_ToByte(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Char": return _utils.Adapter.LambdaConvert_ToChar(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.DateTime": return _utils.Adapter.LambdaConvert_ToDateTime(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Decimal": return _utils.Adapter.LambdaConvert_ToDecimal(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Double": return _utils.Adapter.LambdaConvert_ToDouble(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Int16": return _utils.Adapter.LambdaConvert_ToInt16(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Int32": return _utils.Adapter.LambdaConvert_ToInt32(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Int64": return _utils.Adapter.LambdaConvert_ToInt64(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.SByte": return _utils.Adapter.LambdaConvert_ToSByte(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Single": return _utils.Adapter.LambdaConvert_ToSingle(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.UInt16": return _utils.Adapter.LambdaConvert_ToUInt16(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.UInt32": return _utils.Adapter.LambdaConvert_ToUInt32(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.UInt64": return _utils.Adapter.LambdaConvert_ToUInt64(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
case "System.Guid": return _utils.Adapter.LambdaConvert_ToGuid(callExp.Method.DeclaringType, getExp(callExp.Arguments[0]));
|
||||
}
|
||||
break;
|
||||
case "NewGuid":
|
||||
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString())
|
||||
{
|
||||
case "System.Guid": return _utils.Adapter.LambdaGuid_NewGuid;
|
||||
}
|
||||
break;
|
||||
case "Next":
|
||||
if (callExp.Object?.Type == typeof(Random)) return _utils.Adapter.LambdaRandom_Next;
|
||||
break;
|
||||
case "NextDouble":
|
||||
if (callExp.Object?.Type == typeof(Random)) return _utils.Adapter.LambdaRandom_NextDouble;
|
||||
break;
|
||||
case "Random":
|
||||
if (callExp.Method.DeclaringType.IsNumberType()) return _utils.Adapter.LambdaRandom_NextDouble;
|
||||
break;
|
||||
case "ToString":
|
||||
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? _utils.Adapter.LambdaConvert_ToString(callExp.Object.Type, getExp(callExp.Object)) : null;
|
||||
break;
|
||||
}
|
||||
|
||||
var objExp = callExp.Object;
|
||||
var objType = objExp?.Type;
|
||||
if (objType?.FullName == "System.Byte[]") return null;
|
||||
|
||||
var argIndex = 0;
|
||||
if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable))
|
||||
{
|
||||
objExp = callExp.Arguments.FirstOrDefault();
|
||||
objType = objExp?.Type;
|
||||
argIndex++;
|
||||
}
|
||||
if (objType == null) objType = callExp.Method.DeclaringType;
|
||||
if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType))
|
||||
{
|
||||
var left = objExp == null ? null : getExp(objExp);
|
||||
switch (callExp.Method.Name)
|
||||
{
|
||||
case "Contains":
|
||||
//判断 in
|
||||
return $"({getExp(callExp.Arguments[argIndex])}) in {left}";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExpressionType.NewArrayInit:
|
||||
var arrExp = exp as NewArrayExpression;
|
||||
var arrSb = new StringBuilder();
|
||||
arrSb.Append("(");
|
||||
for (var a = 0; a < arrExp.Expressions.Count; a++)
|
||||
{
|
||||
if (a > 0) arrSb.Append(",");
|
||||
arrSb.Append(getExp(arrExp.Expressions[a]));
|
||||
}
|
||||
if (arrSb.Length == 1) arrSb.Append("NULL");
|
||||
return arrSb.Append(")").ToString();
|
||||
case ExpressionType.ListInit:
|
||||
var listExp = exp as ListInitExpression;
|
||||
var listSb = new StringBuilder();
|
||||
listSb.Append("(");
|
||||
for (var a = 0; a < listExp.Initializers.Count; a++)
|
||||
{
|
||||
if (listExp.Initializers[a].Arguments.Any() == false) continue;
|
||||
if (a > 0) listSb.Append(",");
|
||||
listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
|
||||
}
|
||||
if (listSb.Length == 1) listSb.Append("NULL");
|
||||
return listSb.Append(")").ToString();
|
||||
case ExpressionType.New:
|
||||
var newExp = exp as NewExpression;
|
||||
if (typeof(IList).IsAssignableFrom(newExp.Type))
|
||||
{
|
||||
if (newExp.Arguments.Count == 0) return "(NULL)";
|
||||
if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false) return "(NULL)";
|
||||
return getExp(newExp.Arguments[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc)
|
||||
{
|
||||
if (exp.Expression == null)
|
||||
{
|
||||
switch (exp.Member.Name)
|
||||
{
|
||||
case "Empty": return "''";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var left = ExpressionLambdaToSql(exp.Expression, tsc);
|
||||
switch (exp.Member.Name)
|
||||
{
|
||||
case "Length": return _utils.Adapter.LambdaString_Length(left);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc)
|
||||
{
|
||||
if (exp.Expression == null)
|
||||
{
|
||||
switch (exp.Member.Name)
|
||||
{
|
||||
case "Now": return _utils.Adapter.LambdaDateTime_Now;
|
||||
case "UtcNow": return _utils.Adapter.LambdaDateTime_UtcNow;
|
||||
case "Today": return _utils.Adapter.LambdaDateTime_Today;
|
||||
case "MinValue": return _utils.Adapter.LambdaDateTime_MinValue;
|
||||
case "MaxValue": return _utils.Adapter.LambdaDateTime_MaxValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var left = ExpressionLambdaToSql(exp.Expression, tsc);
|
||||
switch (exp.Member.Name)
|
||||
{
|
||||
case "Date": return _utils.Adapter.LambdaDateTime_Date(left);
|
||||
case "TimeOfDay": return _utils.Adapter.LambdaDateTime_TimeOfDay(left);
|
||||
case "DayOfWeek": return _utils.Adapter.LambdaDateTime_DayOfWeek(left);
|
||||
case "Day": return _utils.Adapter.LambdaDateTime_Day(left);
|
||||
case "DayOfYear": return _utils.Adapter.LambdaDateTime_DayOfYear(left);
|
||||
case "Month": return _utils.Adapter.LambdaDateTime_Month(left);
|
||||
case "Year": return _utils.Adapter.LambdaDateTime_Year(left);
|
||||
case "Hour": return _utils.Adapter.LambdaDateTime_Hour(left);
|
||||
case "Minute": return _utils.Adapter.LambdaDateTime_Minute(left);
|
||||
case "Second": return _utils.Adapter.LambdaDateTime_Second(left);
|
||||
case "Millisecond": return _utils.Adapter.LambdaDateTime_Millisecond(left);
|
||||
case "Ticks": return _utils.Adapter.LambdaDateTime_Ticks(left);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc)
|
||||
{
|
||||
if (exp.Expression == null)
|
||||
{
|
||||
switch (exp.Member.Name)
|
||||
{
|
||||
case "Zero": return "0";
|
||||
case "MinValue": return "-922337203685477580"; //微秒 Ticks / 10
|
||||
case "MaxValue": return "922337203685477580";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var left = ExpressionLambdaToSql(exp.Expression, tsc);
|
||||
switch (exp.Member.Name)
|
||||
{
|
||||
case "Days": return _utils.Adapter.LambdaMath_Floor($"({left})/{60 * 60 * 24}");
|
||||
case "Hours": return _utils.Adapter.LambdaMath_Floor($"({left})/{60 * 60}%24");
|
||||
case "Milliseconds": return $"({_utils.Adapter.CastSql(left, _utils.Adapter.MappingOdbcTypeBigInt)}*1000)";
|
||||
case "Minutes": return _utils.Adapter.LambdaMath_Floor($"({left})/60%60");
|
||||
case "Seconds": return $"(({left})%60)";
|
||||
case "Ticks": return $"({_utils.Adapter.CastSql(left, _utils.Adapter.MappingOdbcTypeBigInt)}*10000000)";
|
||||
case "TotalDays": return $"(({left})/{60 * 60 * 24})";
|
||||
case "TotalHours": return $"(({left})/{60 * 60})";
|
||||
case "TotalMilliseconds": return $"({_utils.Adapter.CastSql(left, _utils.Adapter.MappingOdbcTypeBigInt)}*1000)";
|
||||
case "TotalMinutes": return $"(({left})/60)";
|
||||
case "TotalSeconds": return $"({left})";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc)
|
||||
{
|
||||
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
|
||||
if (exp.Object == null)
|
||||
{
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "IsNullOrEmpty": return _utils.Adapter.LambdaString_IsNullOrEmpty(getExp(exp.Arguments[0]));
|
||||
case "IsNullOrWhiteSpace": return _utils.Adapter.LambdaString_IsNullOrWhiteSpace(getExp(exp.Arguments[0]));
|
||||
case "Concat": return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), exp.Arguments.Select(a => a.Type).ToArray());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var left = getExp(exp.Object);
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "StartsWith":
|
||||
case "EndsWith":
|
||||
case "Contains":
|
||||
var args0Value = getExp(exp.Arguments[0]);
|
||||
if (args0Value == "NULL") return $"({left}) IS NULL";
|
||||
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"({_common.StringConcat(new string[] { args0Value, "'%'" }, new[] { typeof(int), typeof(string) })})")}";
|
||||
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"({_common.StringConcat(new string[] { "'%'", args0Value }, new[] { typeof(string), typeof(int) })})")}";
|
||||
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
|
||||
return $"({left}) LIKE ({_common.StringConcat(new string[] { "'%'", args0Value, "'%'" }, new[] { typeof(string), typeof(int), typeof(string)})})";
|
||||
case "ToLower": return _utils.Adapter.LambdaString_ToLower(left);
|
||||
case "ToUpper": return _utils.Adapter.LambdaString_ToUpper(left);
|
||||
case "Substring":
|
||||
var substrArgs1 = getExp(exp.Arguments[0]);
|
||||
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
|
||||
else substrArgs1 += "+1";
|
||||
if (exp.Arguments.Count == 1) return _utils.Adapter.LambdaString_Substring(left, substrArgs1, null);
|
||||
return _utils.Adapter.LambdaString_Substring(left, substrArgs1, getExp(exp.Arguments[1]));
|
||||
case "IndexOf":
|
||||
var indexOfFindStr = getExp(exp.Arguments[0]);
|
||||
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32")
|
||||
{
|
||||
var locateArgs1 = getExp(exp.Arguments[1]);
|
||||
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
|
||||
else locateArgs1 += "+1";
|
||||
return _utils.Adapter.LambdaString_IndexOf(left, indexOfFindStr, locateArgs1);
|
||||
}
|
||||
return _utils.Adapter.LambdaString_IndexOf(left, indexOfFindStr, null);
|
||||
case "PadLeft":
|
||||
if (exp.Arguments.Count == 1) return _utils.Adapter.LambdaString_PadLeft(left, getExp(exp.Arguments[0]), null);
|
||||
return _utils.Adapter.LambdaString_PadLeft(left, getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
case "PadRight":
|
||||
if (exp.Arguments.Count == 1) return _utils.Adapter.LambdaString_PadRight(left, getExp(exp.Arguments[0]), null);
|
||||
return _utils.Adapter.LambdaString_PadRight(left, getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
case "Trim": return _utils.Adapter.LambdaString_Trim(left);
|
||||
case "TrimStart": return _utils.Adapter.LambdaString_TrimStart(left);
|
||||
case "TrimEnd": return _utils.Adapter.LambdaString_TrimEnd(left);
|
||||
case "Replace": return _utils.Adapter.LambdaString_Replace(left, getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
case "CompareTo": return _utils.Adapter.LambdaString_CompareTo(left, getExp(exp.Arguments[0]));
|
||||
case "Equals": return _utils.Adapter.LambdaString_Equals(left, getExp(exp.Arguments[0]));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc)
|
||||
{
|
||||
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "Abs": return _utils.Adapter.LambdaMath_Abs(getExp(exp.Arguments[0]));
|
||||
case "Sign": return _utils.Adapter.LambdaMath_Sign(getExp(exp.Arguments[0]));
|
||||
case "Floor": return _utils.Adapter.LambdaMath_Floor(getExp(exp.Arguments[0]));
|
||||
case "Ceiling": return _utils.Adapter.LambdaMath_Ceiling(getExp(exp.Arguments[0]));
|
||||
case "Round":
|
||||
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return _utils.Adapter.LambdaMath_Round(getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
return _utils.Adapter.LambdaMath_Round(getExp(exp.Arguments[0]), "0");
|
||||
case "Exp": return _utils.Adapter.LambdaMath_Exp(getExp(exp.Arguments[0]));
|
||||
case "Log": return _utils.Adapter.LambdaMath_Log(getExp(exp.Arguments[0]));
|
||||
case "Log10": return _utils.Adapter.LambdaMath_Log10(getExp(exp.Arguments[0]));
|
||||
case "Pow": return _utils.Adapter.LambdaMath_Pow(getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
case "Sqrt": return _utils.Adapter.LambdaMath_Sqrt(getExp(exp.Arguments[0]));
|
||||
case "Cos": return _utils.Adapter.LambdaMath_Cos(getExp(exp.Arguments[0]));
|
||||
case "Sin": return _utils.Adapter.LambdaMath_Sin(getExp(exp.Arguments[0]));
|
||||
case "Tan": return _utils.Adapter.LambdaMath_Tan(getExp(exp.Arguments[0]));
|
||||
case "Acos": return _utils.Adapter.LambdaMath_Acos(getExp(exp.Arguments[0]));
|
||||
case "Asin": return _utils.Adapter.LambdaMath_Asin(getExp(exp.Arguments[0]));
|
||||
case "Atan": return _utils.Adapter.LambdaMath_Atan(getExp(exp.Arguments[0]));
|
||||
case "Atan2": return _utils.Adapter.LambdaMath_Atan2(getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
case "Truncate": return _utils.Adapter.LambdaMath_Truncate(getExp(exp.Arguments[0]));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc)
|
||||
{
|
||||
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
|
||||
if (exp.Object == null)
|
||||
{
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "Compare": return _utils.Adapter.LambdaDateTime_CompareTo(getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
case "DaysInMonth": return _utils.Adapter.LambdaDateTime_DaysInMonth(getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
case "Equals": return _utils.Adapter.LambdaDateTime_Equals(getExp(exp.Arguments[0]), getExp(exp.Arguments[1]));
|
||||
|
||||
case "IsLeapYear": return _utils.Adapter.LambdaDateTime_IsLeapYear(getExp(exp.Arguments[0]));
|
||||
|
||||
case "Parse": return _utils.Adapter.LambdaConvert_ToDateTime(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ParseExact":
|
||||
case "TryParse":
|
||||
case "TryParseExact": return _utils.Adapter.LambdaConvert_ToDateTime(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var left = getExp(exp.Object);
|
||||
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "Add": return _utils.Adapter.LambdaDateTime_Add(left, args1);
|
||||
case "AddDays": return _utils.Adapter.LambdaDateTime_AddDays(left, args1);
|
||||
case "AddHours": return _utils.Adapter.LambdaDateTime_AddHours(left, args1);
|
||||
case "AddMilliseconds": return _utils.Adapter.LambdaDateTime_AddMilliseconds(left, args1);
|
||||
case "AddMinutes": return _utils.Adapter.LambdaDateTime_AddMinutes(left, args1);
|
||||
case "AddMonths": return _utils.Adapter.LambdaDateTime_AddMonths(left, args1);
|
||||
case "AddSeconds": return _utils.Adapter.LambdaDateTime_AddSeconds(left, args1);
|
||||
case "AddTicks": return _utils.Adapter.LambdaDateTime_AddTicks(left, args1);
|
||||
case "AddYears": return _utils.Adapter.LambdaDateTime_AddYears(left, args1);
|
||||
case "Subtract":
|
||||
switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault() : exp.Arguments[0].Type).FullName)
|
||||
{
|
||||
case "System.DateTime": return _utils.Adapter.LambdaDateTime_Subtract(left, args1);
|
||||
case "System.TimeSpan": return _utils.Adapter.LambdaDateTime_SubtractTimeSpan(left, args1);
|
||||
}
|
||||
break;
|
||||
case "Equals": return _utils.Adapter.LambdaDateTime_Equals(left, args1);
|
||||
case "CompareTo": return _utils.Adapter.LambdaDateTime_CompareTo(left, args1);
|
||||
case "ToString": return exp.Arguments.Count == 0 ? _utils.Adapter.LambdaDateTime_ToString(left) : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual string LambdaDateSpan_Add(string operand, string value) => $"({operand}+{value})";
|
||||
public virtual string LambdaDateSpan_Subtract(string operand, string value) => $"({operand}-({value}))";
|
||||
public virtual string LambdaDateSpan_Equals(string oldvalue, string newvalue) => $"({oldvalue} = {newvalue})";
|
||||
public virtual string LambdaDateSpan_CompareTo(string oldvalue, string newvalue) => $"({oldvalue}-({newvalue}))";
|
||||
|
||||
public override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc)
|
||||
{
|
||||
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
|
||||
if (exp.Object == null)
|
||||
{
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
|
||||
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
|
||||
case "FromDays": return $"(({getExp(exp.Arguments[0])})*{60 * 60 * 24})";
|
||||
case "FromHours": return $"(({getExp(exp.Arguments[0])})*{60 * 60})";
|
||||
case "FromMilliseconds": return $"(({getExp(exp.Arguments[0])})/1000)";
|
||||
case "FromMinutes": return $"(({getExp(exp.Arguments[0])})*60)";
|
||||
case "FromSeconds": return $"({getExp(exp.Arguments[0])})";
|
||||
case "FromTicks": return $"(({getExp(exp.Arguments[0])})/10000000)";
|
||||
case "Parse": return _utils.Adapter.LambdaConvert_ToInt64(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ParseExact":
|
||||
case "TryParse":
|
||||
case "TryParseExact": return _utils.Adapter.LambdaConvert_ToInt64(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var left = getExp(exp.Object);
|
||||
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "Add": return $"({left}+{args1})";
|
||||
case "Subtract": return $"({left}-({args1}))";
|
||||
case "Equals": return $"({left} = {args1})";
|
||||
case "CompareTo": return $"({left}-({args1}))";
|
||||
case "ToString": return _utils.Adapter.LambdaConvert_ToString(exp.Type, left);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc)
|
||||
{
|
||||
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
|
||||
if (exp.Object == null)
|
||||
{
|
||||
switch (exp.Method.Name)
|
||||
{
|
||||
case "ToBoolean": return _utils.Adapter.LambdaConvert_ToBoolean(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToByte": return _utils.Adapter.LambdaConvert_ToByte(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToChar": return _utils.Adapter.LambdaConvert_ToChar(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToDateTime": return _utils.Adapter.LambdaConvert_ToDateTime(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToDecimal": return _utils.Adapter.LambdaConvert_ToDecimal(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToDouble": return _utils.Adapter.LambdaConvert_ToDouble(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToInt16": return _utils.Adapter.LambdaConvert_ToInt16(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToInt32": return _utils.Adapter.LambdaConvert_ToInt32(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToInt64": return _utils.Adapter.LambdaConvert_ToInt64(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToSByte": return _utils.Adapter.LambdaConvert_ToSByte(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToSingle": return _utils.Adapter.LambdaConvert_ToSingle(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToString": return _utils.Adapter.LambdaConvert_ToString(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToUInt16": return _utils.Adapter.LambdaConvert_ToUInt16(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToUInt32": return _utils.Adapter.LambdaConvert_ToUInt32(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
case "ToUInt64": return _utils.Adapter.LambdaConvert_ToUInt64(exp.Arguments[0].Type, getExp(exp.Arguments[0]));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
113
Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs
Normal file
113
Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using FreeSql.Odbc.Default;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
public class OdbcProvider<TMark> : IFreeSql<TMark>
|
||||
{
|
||||
|
||||
public ISelect<T1> Select<T1>() where T1 : class => new OdbcSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new OdbcSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
public IInsert<T1> Insert<T1>() where T1 : class => new OdbcInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
|
||||
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||
public IUpdate<T1> Update<T1>() where T1 : class => new OdbcUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OdbcUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
public IDelete<T1> Delete<T1>() where T1 : class => new OdbcDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OdbcDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
|
||||
public IAdo Ado { get; }
|
||||
public IAop Aop { get; }
|
||||
public ICodeFirst CodeFirst { get; }
|
||||
public IDbFirst DbFirst => throw new NotImplementedException("FreeSql.Odbc.Default 未实现该功能");
|
||||
|
||||
/// <summary>
|
||||
/// 生成一个普通访问功能的 IFreeSql 对象,用来访问 odbc
|
||||
/// </summary>
|
||||
/// <param name="masterConnectionString"></param>
|
||||
/// <param name="slaveConnectionString"></param>
|
||||
/// <param name="adapter">适配器</param>
|
||||
public OdbcProvider(string masterConnectionString, string[] slaveConnectionString)
|
||||
{
|
||||
this.InternalCommonUtils = new OdbcUtils(this);
|
||||
this.InternalCommonExpression = new OdbcExpression(this.InternalCommonUtils);
|
||||
|
||||
this.Ado = new OdbcAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString);
|
||||
this.Aop = new AopProvider();
|
||||
|
||||
this.CodeFirst = new OdbcCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
|
||||
|
||||
var _utils = InternalCommonUtils as OdbcUtils;
|
||||
//处理 MaxLength
|
||||
this.Aop.ConfigEntityProperty += new EventHandler<Aop.ConfigEntityPropertyEventArgs>((s, e) =>
|
||||
{
|
||||
object[] attrs = null;
|
||||
try
|
||||
{
|
||||
attrs = e.Property.GetCustomAttributes(false).ToArray(); //.net core 反射存在版本冲突问题,导致该方法异常
|
||||
}
|
||||
catch { }
|
||||
|
||||
var maxlenAttr = attrs.Where(a => {
|
||||
return ((a as Attribute)?.TypeId as Type)?.Name == "MaxLengthAttribute";
|
||||
}).FirstOrDefault();
|
||||
if (maxlenAttr != null)
|
||||
{
|
||||
var lenProp = maxlenAttr.GetType().GetProperties().Where(a => a.PropertyType.IsNumberType()).FirstOrDefault();
|
||||
if (lenProp != null && int.TryParse(string.Concat(lenProp.GetValue(maxlenAttr, null)), out var tryval))
|
||||
{
|
||||
if (tryval != 0)
|
||||
{
|
||||
switch (this.Ado.DataType)
|
||||
{
|
||||
case DataType.Sqlite:
|
||||
e.ModifyResult.DbType = tryval > 0 ? $"{_utils.Adapter.MappingOdbcTypeVarChar}({tryval})" : _utils.Adapter.MappingOdbcTypeText;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal CommonUtils InternalCommonUtils { get; }
|
||||
internal CommonExpression InternalCommonExpression { get; }
|
||||
|
||||
public void Transaction(Action handler) => Ado.Transaction(handler);
|
||||
|
||||
public void Transaction(Action handler, TimeSpan timeout) => Ado.Transaction(handler, timeout);
|
||||
|
||||
~OdbcProvider()
|
||||
{
|
||||
this.Dispose();
|
||||
}
|
||||
bool _isdisposed = false;
|
||||
public void Dispose()
|
||||
{
|
||||
if (_isdisposed) return;
|
||||
try
|
||||
{
|
||||
(this.Ado as AdoProvider)?.Dispose();
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeSqlOdbcGlobalExtensions._dicOdbcAdater.TryRemove(this as IFreeSql, out var tryada);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial class FreeSqlOdbcGlobalExtensions
|
||||
{
|
||||
internal static OdbcAdapter DefaultOdbcAdapter = new OdbcAdapter();
|
||||
internal static ConcurrentDictionary<IFreeSql, OdbcAdapter> _dicOdbcAdater = new ConcurrentDictionary<IFreeSql, OdbcAdapter>();
|
||||
public static void SetOdbcAdapter(this IFreeSql that, OdbcAdapter adapter) => _dicOdbcAdater.AddOrUpdate(that, adapter, (fsql, old) => adapter);
|
||||
internal static OdbcAdapter GetOdbcAdapter(this IFreeSql that) => _dicOdbcAdater.TryGetValue(that, out var tryada) ? tryada : DefaultOdbcAdapter;
|
||||
}
|
73
Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs
Normal file
73
Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using FreeSql.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.Odbc;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql.Odbc.Default
|
||||
{
|
||||
|
||||
public class OdbcUtils : CommonUtils
|
||||
{
|
||||
public OdbcUtils(IFreeSql orm) : base(orm) { }
|
||||
public OdbcAdapter Adapter => _orm.GetOdbcAdapter();
|
||||
|
||||
public override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
|
||||
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
|
||||
var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName), Value = value };
|
||||
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
|
||||
if (tp != null) ret.OdbcType = (OdbcType)tp.Value;
|
||||
_params?.Add(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
|
||||
Utils.GetDbParamtersByObject<OdbcParameter>(sql, obj, null, (name, type, value) =>
|
||||
{
|
||||
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
|
||||
var ret = new OdbcParameter { ParameterName = $"@{name}", Value = value };
|
||||
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
|
||||
if (tp != null) ret.OdbcType = (OdbcType)tp.Value;
|
||||
return ret;
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbc(args);
|
||||
public override string QuoteSqlName(string name)
|
||||
{
|
||||
var nametrim = name.Trim();
|
||||
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
|
||||
return nametrim; //原生SQL
|
||||
//return $"[{nametrim.TrimStart('[').TrimEnd(']').Replace(".", "].[")}]";
|
||||
return $"{Adapter.QuoteSqlNameLeft}{nametrim.TrimStart(Adapter.QuoteSqlNameLeft).TrimEnd(Adapter.QuoteSqlNameRight).Replace(".", $"{Adapter.QuoteSqlNameRight}.{Adapter.QuoteSqlNameLeft}")}{Adapter.QuoteSqlNameRight}";
|
||||
}
|
||||
public override string TrimQuoteSqlName(string name)
|
||||
{
|
||||
var nametrim = name.Trim();
|
||||
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
|
||||
return nametrim; //原生SQL
|
||||
//return $"{nametrim.TrimStart('[').TrimEnd(']').Replace("].[", ".").Replace(".[", ".")}";
|
||||
return $"{nametrim.TrimStart(Adapter.QuoteSqlNameLeft).TrimEnd(Adapter.QuoteSqlNameRight).Replace($"{Adapter.QuoteSqlNameRight}.{Adapter.QuoteSqlNameLeft}", ".").Replace($".{Adapter.QuoteSqlNameLeft}", ".")}";
|
||||
}
|
||||
public override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
|
||||
public override string IsNull(string sql, object value) => Adapter.IsNullSql(sql, value);
|
||||
public override string StringConcat(string[] objs, Type[] types) => Adapter.ConcatSql(objs, types);
|
||||
public override string Mod(string left, string right, Type leftType, Type rightType) => Adapter.Mod(left, right, leftType, rightType);
|
||||
public override string Div(string left, string right, Type leftType, Type rightType) => Adapter.Div(left, right, leftType, rightType);
|
||||
|
||||
public override string QuoteWriteParamter(Type type, string paramterName) => paramterName;
|
||||
public override string QuoteReadColumn(Type type, string columnName) => Adapter.FieldSql(type, columnName);
|
||||
|
||||
public override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
if (type == typeof(byte[])) return Adapter.ByteRawSql(value);
|
||||
return FormatSql("{0}", value, 1);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user