mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 12:28:15 +08:00
Merge branch 'master' into fix_tree
This commit is contained in:
@ -60,6 +60,13 @@ namespace FreeSql
|
||||
/// 自定义适配器,访问任何数据库<para></para>
|
||||
/// 注意:该类型不提供 DbFirst/CodeFirst 功能
|
||||
/// </summary>
|
||||
Custom
|
||||
Custom,
|
||||
|
||||
ClickHouse,
|
||||
|
||||
/// <summary>
|
||||
/// 天津南大通用数据技术股份有限公司成立于2004年,是国产数据库、大数据领域的知名企业,基于 Odbc 的实现
|
||||
/// </summary>
|
||||
GBase
|
||||
}
|
||||
}
|
||||
|
@ -45,9 +45,18 @@ namespace FreeSql.DatabaseModel
|
||||
/// </summary>
|
||||
public bool IsNullable { get; set; }
|
||||
/// <summary>
|
||||
/// 备注,早期编码时少按了一个字母,请使用 Comment
|
||||
/// </summary>
|
||||
[Obsolete("早期编码时少按了一个字母,请使用 Comment")]
|
||||
public string Coment
|
||||
{
|
||||
get => Comment;
|
||||
set => Comment = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Coment { get; set; }
|
||||
public string Comment { get; set; }
|
||||
/// <summary>
|
||||
/// 数据库默认值
|
||||
/// </summary>
|
||||
|
@ -59,6 +59,10 @@ namespace FreeSql
|
||||
providerType = Type.GetType("FreeSql.Firebird.FirebirdProvider`1,FreeSql.Provider.Firebird")?.MakeGenericType(connType);
|
||||
if (providerType == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.Firebird.dll,可前往 nuget 下载");
|
||||
break;
|
||||
case "ClickHouseConnection":
|
||||
providerType = Type.GetType("FreeSql.ClickHouse.ClickHouseProvider`1,FreeSql.Provider.ClickHouse")?.MakeGenericType(connType);
|
||||
if (providerType == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.ClickHouse.dll,可前往 nuget 下载");
|
||||
break;
|
||||
default:
|
||||
throw new Exception("未实现");
|
||||
}
|
||||
|
@ -140,6 +140,17 @@ namespace FreeSql
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注意:使用者自己承担【注入风险】
|
||||
/// </summary>
|
||||
/// <param name="sql"></param>
|
||||
/// <returns></returns>
|
||||
static bool InternalRawSql([RawValue] string sql)
|
||||
{
|
||||
expContext.Value.Result = sql;
|
||||
return false;
|
||||
}
|
||||
|
||||
#region 大小判断
|
||||
/// <summary>
|
||||
/// 大于 >
|
||||
@ -460,6 +471,15 @@ namespace FreeSql
|
||||
expContext.Result = $"list({expContext.ParsedContent["column"]},{expContext.ParsedContent["delimiter"]})";
|
||||
return null;
|
||||
}
|
||||
public static string StringJoinGBaseWmConcatText(object column, object delimiter)
|
||||
{
|
||||
if (expContext.ParsedContent["delimiter"] == "','")
|
||||
expContext.Result = $"wm_concat_text({expContext.ParsedContent["column"]})";
|
||||
else
|
||||
throw new NotImplementedException("GBase 暂时不支持逗号以外的分割符");
|
||||
//expContext.Result = $"replace(wm_concat_text({expContext.ParsedContent["column"]}), ',', {expContext.ParsedContent["delimiter"]})";
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using FreeSql.Internal.Model;
|
||||
using FreeSql.Internal.ObjectPool;
|
||||
using System;
|
||||
using System.Collections;
|
||||
@ -58,7 +59,7 @@ public static partial class FreeSqlGlobalExtensions
|
||||
/// <param name="type"></param>
|
||||
/// <param name="isNameSpace"></param>
|
||||
/// <returns></returns>
|
||||
internal static string DisplayCsharp(this Type type, bool isNameSpace = true)
|
||||
public static string DisplayCsharp(this Type type, bool isNameSpace = true)
|
||||
{
|
||||
if (type == null) return null;
|
||||
if (type == typeof(void)) return "void";
|
||||
@ -418,9 +419,25 @@ public static partial class FreeSqlGlobalExtensions
|
||||
if (select._orm.CodeFirst.IsSyncStructureToLower) cteName = cteName.ToLower();
|
||||
if (select._orm.CodeFirst.IsSyncStructureToUpper) cteName = cteName.ToUpper();
|
||||
|
||||
switch (select._orm.Ado.DataType) //MySql5.6
|
||||
switch (select._orm.Ado.DataType)
|
||||
{
|
||||
case DataType.MySql:
|
||||
case DataType.GBase:
|
||||
//select t.parentid, t.subid, level
|
||||
//from a_test t
|
||||
//start with subid = '7'
|
||||
//connect by prior subid = parentid;
|
||||
var gbsb = new StringBuilder();
|
||||
var gbsbWhere = select._where.ToString();
|
||||
select._where.Clear();
|
||||
if (gbsbWhere.StartsWith(" AND ")) gbsbWhere = gbsbWhere.Remove(0, 5);
|
||||
gbsb.Append(select._tosqlAppendContent).Append(" \r\nstart with ").Append(gbsbWhere).Append(" \r\nconnect by prior ");
|
||||
if (up) gbsb.Append("a.").Append(select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)).Append(" = ").Append("a.").Append(select._commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name));
|
||||
else gbsb.Append("a.").Append(select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)).Append(" = ").Append("a.").Append(select._commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name));
|
||||
var gbswstr = gbsb.ToString();
|
||||
gbsb.Clear();
|
||||
select.AsAlias((_, old) => $"{old} {gbswstr}");
|
||||
return select;
|
||||
case DataType.MySql: //MySql5.6
|
||||
case DataType.OdbcMySql:
|
||||
var mysqlConnectionString = select._orm.Ado?.ConnectionString ?? select._connection?.ConnectionString ?? "";
|
||||
if (_dicMySqlVersion.TryGetValue(mysqlConnectionString, out var mysqlVersion) == false)
|
||||
@ -495,6 +512,7 @@ JOIN {select._commonUtils.QuoteSqlName(tb.DbName)} a ON cte_tbc.cte_id = a.{sele
|
||||
case DataType.SqlServer:
|
||||
case DataType.OdbcSqlServer:
|
||||
case DataType.Firebird:
|
||||
case DataType.ClickHouse:
|
||||
sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, Expression.Call(typeof(Convert).GetMethod("ToString", new Type[] { typeof(string) }), pathSelector?.Body), null, null, null);
|
||||
break;
|
||||
default:
|
||||
@ -503,11 +521,11 @@ JOIN {select._commonUtils.QuoteSqlName(tb.DbName)} a ON cte_tbc.cte_id = a.{sele
|
||||
}
|
||||
sql1ctePath = $"{sql1ctePath} as cte_path, ";
|
||||
}
|
||||
var sql1 = select.ToSql($"0 as cte_level, {sql1ctePath}{select.GetAllFieldExpressionTreeLevel2().Field}").Trim();
|
||||
var sql1 = select.ToSql($"0 as cte_level, {sql1ctePath}{select.GetAllFieldExpressionTreeLevel2(false).Field}").Trim();
|
||||
|
||||
select._where.Clear();
|
||||
select.As("wct2");
|
||||
var sql2Field = select.GetAllFieldExpressionTreeLevel2().Field;
|
||||
var sql2Field = select.GetAllFieldExpressionTreeLevel2(false).Field;
|
||||
var sql2InnerJoinOn = up == false ?
|
||||
string.Join(" and ", tbref.Columns.Select((a, z) => $"wct2.{select._commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)} = wct1.{select._commonUtils.QuoteSqlName(a.Attribute.Name)}")) :
|
||||
string.Join(" and ", tbref.Columns.Select((a, z) => $"wct2.{select._commonUtils.QuoteSqlName(a.Attribute.Name)} = wct1.{select._commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)}"));
|
||||
@ -579,6 +597,7 @@ JOIN {select._commonUtils.QuoteSqlName(tb.DbName)} a ON cte_tbc.cte_id = a.{sele
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.Dameng: //递归 WITH 子句必须具有列别名列表
|
||||
case DataType.OdbcDameng:
|
||||
case DataType.GBase:
|
||||
nsselsb.Append($"(cte_level, {(pathSelector == null ? "" : "cte_path, ")}{sql2Field.Replace("wct2.", "")})");
|
||||
break;
|
||||
}
|
||||
@ -609,6 +628,7 @@ SELECT ");
|
||||
{
|
||||
case DataType.MySql:
|
||||
case DataType.OdbcMySql:
|
||||
case DataType.ClickHouse:
|
||||
return that.OrderBy("rand()");
|
||||
case DataType.SqlServer:
|
||||
case DataType.OdbcSqlServer:
|
||||
@ -634,4 +654,371 @@ SELECT ");
|
||||
throw new NotSupportedException($"{s0p._orm.Ado.DataType} 不支持 OrderByRandom 随机排序");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IFreeSql Insert/Update/InsertOrUpdate/Delete Dictionary<string, object>
|
||||
/// <summary>
|
||||
/// 插入数据字典 Dictionary<string, object>
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static InsertDictImpl InsertDict(this IFreeSql freesql, Dictionary<string, object> source)
|
||||
{
|
||||
var insertDict = new InsertDictImpl(freesql);
|
||||
insertDict._insertProvider.AppendData(source);
|
||||
return insertDict;
|
||||
}
|
||||
/// <summary>
|
||||
/// 插入数据字典,传入 Dictionary<string, object> 集合
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static InsertDictImpl InsertDict(this IFreeSql freesql, IEnumerable<Dictionary<string, object>> source)
|
||||
{
|
||||
var insertDict = new InsertDictImpl(freesql);
|
||||
insertDict._insertProvider.AppendData(source);
|
||||
return insertDict;
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新数据字典 Dictionary<string, object>
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static UpdateDictImpl UpdateDict(this IFreeSql freesql, Dictionary<string, object> source)
|
||||
{
|
||||
var updateDict = new UpdateDictImpl(freesql);
|
||||
updateDict._updateProvider.SetSource(source);
|
||||
return updateDict;
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新数据字典,传入 Dictionary<string, object> 集合
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static UpdateDictImpl UpdateDict(this IFreeSql freesql, IEnumerable<Dictionary<string, object>> source)
|
||||
{
|
||||
var updateDict = new UpdateDictImpl(freesql);
|
||||
updateDict._updateProvider.SetSource(source);
|
||||
return updateDict;
|
||||
}
|
||||
/// <summary>
|
||||
/// 插入或更新数据字典,此功能依赖数据库特性(低版本可能不支持),参考如下:<para></para>
|
||||
/// MySql 5.6+: on duplicate key update<para></para>
|
||||
/// PostgreSQL 9.4+: on conflict do update<para></para>
|
||||
/// SqlServer 2008+: merge into<para></para>
|
||||
/// Oracle 11+: merge into<para></para>
|
||||
/// Sqlite: replace into<para></para>
|
||||
/// 达梦: merge into<para></para>
|
||||
/// 人大金仓:on conflict do update<para></para>
|
||||
/// 神通:merge into<para></para>
|
||||
/// MsAccess:不支持<para></para>
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static InsertOrUpdateDictImpl InsertOrUpdateDict(this IFreeSql freesql, Dictionary<string, object> source)
|
||||
{
|
||||
var insertOrUpdateDict = new InsertOrUpdateDictImpl(freesql);
|
||||
insertOrUpdateDict._insertOrUpdateProvider.SetSource(source);
|
||||
return insertOrUpdateDict;
|
||||
}
|
||||
public static InsertOrUpdateDictImpl InsertOrUpdateDict(this IFreeSql freesql, IEnumerable<Dictionary<string, object>> source)
|
||||
{
|
||||
var insertOrUpdateDict = new InsertOrUpdateDictImpl(freesql);
|
||||
insertOrUpdateDict._insertOrUpdateProvider.SetSource(source);
|
||||
return insertOrUpdateDict;
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除数据字典 Dictionary<string, object>
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static DeleteDictImpl DeleteDict(this IFreeSql freesql, Dictionary<string, object> source)
|
||||
{
|
||||
var deleteDict = new DeleteDictImpl(freesql);
|
||||
UpdateProvider<Dictionary<string, object>>.GetDictionaryTableInfo(source, deleteDict._deleteProvider._orm, ref deleteDict._deleteProvider._table);
|
||||
var primarys = UpdateDictImpl.GetPrimarys(deleteDict._deleteProvider._table, source.Keys.ToArray());
|
||||
deleteDict._deleteProvider.Where(deleteDict._deleteProvider._commonUtils.WhereItems(primarys, "", new[] { source }));
|
||||
return deleteDict;
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除数据字典,传入 Dictionary<string, object> 集合
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static DeleteDictImpl DeleteDict(this IFreeSql freesql, IEnumerable<Dictionary<string, object>> source)
|
||||
{
|
||||
DeleteDictImpl deleteDict = null;
|
||||
if (source.Select(a => string.Join(",", a.Keys)).Distinct().Count() == 1)
|
||||
{
|
||||
deleteDict = new DeleteDictImpl(freesql);
|
||||
var sourceFirst = source.FirstOrDefault();
|
||||
UpdateProvider<Dictionary<string, object>>.GetDictionaryTableInfo(sourceFirst, deleteDict._deleteProvider._orm, ref deleteDict._deleteProvider._table);
|
||||
var primarys = UpdateDictImpl.GetPrimarys(deleteDict._deleteProvider._table, sourceFirst.Keys.ToArray());
|
||||
deleteDict._deleteProvider.Where(deleteDict._deleteProvider._commonUtils.WhereItems(primarys, "", source));
|
||||
return deleteDict;
|
||||
}
|
||||
foreach (var item in source)
|
||||
{
|
||||
var tmpDelteDict = DeleteDict(freesql, item);
|
||||
if (deleteDict == null) deleteDict = tmpDelteDict;
|
||||
else deleteDict._deleteProvider._where.Append(" OR ").Append(tmpDelteDict._deleteProvider._where);
|
||||
}
|
||||
return deleteDict ?? new DeleteDictImpl(freesql);
|
||||
}
|
||||
|
||||
#region InsertDictImpl
|
||||
public class InsertDictImpl
|
||||
{
|
||||
internal readonly InsertProvider<Dictionary<string, object>> _insertProvider;
|
||||
internal InsertDictImpl(IFreeSql orm)
|
||||
{
|
||||
_insertProvider = (orm as BaseDbProvider ?? throw new Exception("IFreeSql 无法转换成 BaseDbProvider"))
|
||||
.CreateInsertProvider<Dictionary<string, object>>() as InsertProvider<Dictionary<string, object>>;
|
||||
}
|
||||
|
||||
public InsertDictImpl AsTable(string tableName)
|
||||
{
|
||||
_insertProvider.AsTable(tableName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertDictImpl BatchOptions(int valuesLimit, int parameterLimit, bool autoTransaction = true)
|
||||
{
|
||||
_insertProvider.BatchOptions(valuesLimit, parameterLimit, autoTransaction);
|
||||
return this;
|
||||
}
|
||||
public InsertDictImpl BatchProgress(Action<BatchProgressStatus<Dictionary<string, object>>> callback)
|
||||
{
|
||||
_insertProvider.BatchProgress(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertDictImpl CommandTimeout(int timeout)
|
||||
{
|
||||
_insertProvider.CommandTimeout(timeout);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int ExecuteAffrows() => _insertProvider.ExecuteAffrows();
|
||||
public long ExecuteIdentity() => _insertProvider.ExecuteIdentity();
|
||||
public List<Dictionary<string, object>> ExecuteInserted() => _insertProvider.ExecuteInserted();
|
||||
|
||||
#if net40
|
||||
#else
|
||||
public Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => _insertProvider.ExecuteAffrowsAsync(cancellationToken);
|
||||
public Task<long> ExecuteIdentityAsync(CancellationToken cancellationToken = default) => _insertProvider.ExecuteIdentityAsync(cancellationToken);
|
||||
public Task<List<Dictionary<string, object>>> ExecuteInsertedAsync(CancellationToken cancellationToken = default) => _insertProvider.ExecuteInsertedAsync(cancellationToken);
|
||||
#endif
|
||||
|
||||
public InsertDictImpl NoneParameter(bool isNotCommandParameter = true)
|
||||
{
|
||||
_insertProvider.NoneParameter(isNotCommandParameter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataTable ToDataTable() => _insertProvider.ToDataTable();
|
||||
public string ToSql() => _insertProvider.ToSql();
|
||||
|
||||
public InsertDictImpl WithConnection(DbConnection connection)
|
||||
{
|
||||
_insertProvider.WithConnection(connection);
|
||||
return this;
|
||||
}
|
||||
public InsertDictImpl WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_insertProvider.WithTransaction(transaction);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateDictImpl
|
||||
public class UpdateDictImpl
|
||||
{
|
||||
internal readonly UpdateProvider<Dictionary<string, object>> _updateProvider;
|
||||
internal UpdateDictImpl(IFreeSql orm)
|
||||
{
|
||||
_updateProvider = (orm as BaseDbProvider ?? throw new Exception("IFreeSql 无法转换成 BaseDbProvider"))
|
||||
.CreateUpdateProvider<Dictionary<string, object>>(null) as UpdateProvider<Dictionary<string, object>>;
|
||||
}
|
||||
|
||||
public UpdateDictImpl WherePrimary(params string[] primarys)
|
||||
{
|
||||
_updateProvider._tempPrimarys = GetPrimarys(_updateProvider._table, primarys);
|
||||
return this;
|
||||
}
|
||||
public static ColumnInfo[] GetPrimarys(TableInfo table, params string[] primarys)
|
||||
{
|
||||
if (primarys?.Any() != true) throw new ArgumentException(nameof(primarys));
|
||||
var pks = new List<ColumnInfo>();
|
||||
foreach (var primary in primarys)
|
||||
{
|
||||
if (table.ColumnsByCs.TryGetValue(string.Concat(primary), out var col)) pks.Add(col);
|
||||
else throw new Exception($"GetPrimarys 传递的参数 \"{primary}\" 不正确,它不属于字典数据的键名");
|
||||
}
|
||||
return pks.ToArray();
|
||||
}
|
||||
public static void SetTablePrimary(TableInfo table, params string[] primarys)
|
||||
{
|
||||
foreach (var primary in primarys)
|
||||
{
|
||||
if (table.ColumnsByCs.TryGetValue(string.Concat(primary), out var col)) col.Attribute.IsPrimary = true;
|
||||
else throw new Exception($"GetPrimarys 传递的参数 \"{primary}\" 不正确,它不属于字典数据的键名");
|
||||
}
|
||||
table.Primarys = table.Columns.Where(a => a.Value.Attribute.IsPrimary).Select(a => a.Value).ToArray();
|
||||
}
|
||||
|
||||
public UpdateDictImpl AsTable(string tableName)
|
||||
{
|
||||
_updateProvider.AsTable(tableName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UpdateDictImpl BatchOptions(int rowsLimit, int parameterLimit, bool autoTransaction = true)
|
||||
{
|
||||
_updateProvider.BatchOptions(rowsLimit, parameterLimit, autoTransaction);
|
||||
return this;
|
||||
}
|
||||
public UpdateDictImpl BatchProgress(Action<BatchProgressStatus<Dictionary<string, object>>> callback)
|
||||
{
|
||||
_updateProvider.BatchProgress(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UpdateDictImpl CommandTimeout(int timeout)
|
||||
{
|
||||
_updateProvider.CommandTimeout(timeout);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int ExecuteAffrows() => _updateProvider.ExecuteAffrows();
|
||||
public List<Dictionary<string, object>> ExecuteUpdated() => _updateProvider.ExecuteUpdated();
|
||||
|
||||
#if net40
|
||||
#else
|
||||
public Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => _updateProvider.ExecuteAffrowsAsync(cancellationToken);
|
||||
public Task<List<Dictionary<string, object>>> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => _updateProvider.ExecuteUpdatedAsync(cancellationToken);
|
||||
#endif
|
||||
|
||||
public UpdateDictImpl NoneParameter(bool isNotCommandParameter = true)
|
||||
{
|
||||
_updateProvider.NoneParameter(isNotCommandParameter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public string ToSql() => _updateProvider.ToSql();
|
||||
|
||||
public UpdateDictImpl WithConnection(DbConnection connection)
|
||||
{
|
||||
_updateProvider.WithConnection(connection);
|
||||
return this;
|
||||
}
|
||||
public UpdateDictImpl WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_updateProvider.WithTransaction(transaction);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region InsertOrUpdateDictImpl
|
||||
public class InsertOrUpdateDictImpl
|
||||
{
|
||||
internal readonly InsertOrUpdateProvider<Dictionary<string, object>> _insertOrUpdateProvider;
|
||||
internal InsertOrUpdateDictImpl(IFreeSql orm)
|
||||
{
|
||||
_insertOrUpdateProvider = (orm as BaseDbProvider ?? throw new Exception("IFreeSql 无法转换成 BaseDbProvider"))
|
||||
.CreateInsertOrUpdateProvider<Dictionary<string, object>>() as InsertOrUpdateProvider<Dictionary<string, object>>;
|
||||
}
|
||||
|
||||
public InsertOrUpdateDictImpl WherePrimary(params string[] primarys)
|
||||
{
|
||||
UpdateDictImpl.SetTablePrimary(_insertOrUpdateProvider._table, primarys);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertOrUpdateDictImpl AsTable(string tableName)
|
||||
{
|
||||
_insertOrUpdateProvider.AsTable(tableName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertOrUpdateDictImpl CommandTimeout(int timeout)
|
||||
{
|
||||
_insertOrUpdateProvider.CommandTimeout(timeout);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int ExecuteAffrows() => _insertOrUpdateProvider.ExecuteAffrows();
|
||||
#if net40
|
||||
#else
|
||||
public Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => _insertOrUpdateProvider.ExecuteAffrowsAsync(cancellationToken);
|
||||
#endif
|
||||
public InsertOrUpdateDictImpl IfExistsDoNothing()
|
||||
{
|
||||
_insertOrUpdateProvider.IfExistsDoNothing();
|
||||
return this;
|
||||
}
|
||||
|
||||
public string ToSql() => _insertOrUpdateProvider.ToSql();
|
||||
|
||||
public InsertOrUpdateDictImpl WithConnection(DbConnection connection)
|
||||
{
|
||||
_insertOrUpdateProvider.WithConnection(connection);
|
||||
return this;
|
||||
}
|
||||
public InsertOrUpdateDictImpl WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_insertOrUpdateProvider.WithTransaction(transaction);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DeleteDictImpl
|
||||
public class DeleteDictImpl
|
||||
{
|
||||
internal readonly DeleteProvider<Dictionary<string, object>> _deleteProvider;
|
||||
internal DeleteDictImpl(IFreeSql orm)
|
||||
{
|
||||
_deleteProvider = (orm as BaseDbProvider ?? throw new Exception("IFreeSql 无法转换成 BaseDbProvider"))
|
||||
.CreateDeleteProvider<Dictionary<string, object>>(null) as DeleteProvider<Dictionary<string, object>>;
|
||||
}
|
||||
|
||||
public DeleteDictImpl AsTable(string tableName)
|
||||
{
|
||||
_deleteProvider.AsTable(tableName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteDictImpl CommandTimeout(int timeout)
|
||||
{
|
||||
_deleteProvider.CommandTimeout(timeout);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int ExecuteAffrows() => _deleteProvider.ExecuteAffrows();
|
||||
public List<Dictionary<string, object>> ExecuteDeleted() => _deleteProvider.ExecuteDeleted();
|
||||
|
||||
#if net40
|
||||
#else
|
||||
public Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => _deleteProvider.ExecuteAffrowsAsync(cancellationToken);
|
||||
public Task<List<Dictionary<string, object>>> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => _deleteProvider.ExecuteDeletedAsync(cancellationToken);
|
||||
#endif
|
||||
|
||||
public string ToSql() => _deleteProvider.ToSql();
|
||||
|
||||
public DeleteDictImpl WithConnection(DbConnection connection)
|
||||
{
|
||||
_deleteProvider.WithConnection(connection);
|
||||
return this;
|
||||
}
|
||||
public DeleteDictImpl WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_deleteProvider.WithTransaction(transaction);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net45;net40</TargetFrameworks>
|
||||
<Version>2.6.100</Version>
|
||||
<TargetFrameworks>netstandard2.1;netstandard2.0;net451;net45;net40</TargetFrameworks>
|
||||
<Version>3.2.300</Version>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Authors>FreeSql;ncc;YeXiangQin</Authors>
|
||||
<Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Odbc, 达梦, 人大金仓, 神舟通用, 翰高, And Access</Description>
|
||||
<Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Odbc, 达梦, 人大金仓, 神舟通用, 南大通用, 翰高, And Access</Description>
|
||||
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
@ -34,5 +34,8 @@
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net40'">
|
||||
<DefineConstants>net40</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
|
||||
<DefineConstants>net45</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -515,6 +515,11 @@
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.DatabaseModel.DbColumnInfo.Coment">
|
||||
<summary>
|
||||
备注,早期编码时少按了一个字母,请使用 Comment
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.DatabaseModel.DbColumnInfo.Comment">
|
||||
<summary>
|
||||
备注
|
||||
</summary>
|
||||
@ -656,6 +661,11 @@
|
||||
注意:该类型不提供 DbFirst/CodeFirst 功能
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.DataType.GBase">
|
||||
<summary>
|
||||
天津南大通用数据技术股份有限公司成立于2004年,是国产数据库、大数据领域的知名企业,基于 Odbc 的实现
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSql.AdoNetExtensions.GetIFreeSql(System.Data.IDbConnection)">
|
||||
<summary>
|
||||
获取 IDbConnection 对应的 IFreeSql 实例
|
||||
@ -1202,6 +1212,13 @@
|
||||
<param name="column"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.SqlExt.InternalRawSql(System.String)">
|
||||
<summary>
|
||||
注意:使用者自己承担【注入风险】
|
||||
</summary>
|
||||
<param name="sql"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.SqlExt.GreaterThan``1(``0,``0)">
|
||||
<summary>
|
||||
大于 >
|
||||
@ -1473,6 +1490,13 @@
|
||||
<param name="tableRule"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IDelete`1.AsTable(System.String)">
|
||||
<summary>
|
||||
设置表名
|
||||
</summary>
|
||||
<param name="tableName"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IDelete`1.AsType(System.Type)">
|
||||
<summary>
|
||||
动态Type,在使用 Delete<object> 后使用本方法,指定实体类型
|
||||
@ -1612,6 +1636,13 @@
|
||||
<param name="tableRule"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IInsert`1.AsTable(System.String)">
|
||||
<summary>
|
||||
设置表名
|
||||
</summary>
|
||||
<param name="tableName"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IInsert`1.AsType(System.Type)">
|
||||
<summary>
|
||||
动态Type,在使用 Insert<object> 后使用本方法,指定实体类型
|
||||
@ -1717,6 +1748,13 @@
|
||||
<param name="tableRule"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IInsertOrUpdate`1.AsTable(System.String)">
|
||||
<summary>
|
||||
设置表名
|
||||
</summary>
|
||||
<param name="tableName"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IInsertOrUpdate`1.AsType(System.Type)">
|
||||
<summary>
|
||||
动态Type,在使用 Update<object> 后使用本方法,指定实体类型
|
||||
@ -1792,6 +1830,13 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.ISelect0`2.ToDataTableByPropertyName(System.String[])">
|
||||
<summary>
|
||||
执行SQL查询,返回 properties 指定的实体类属性,并以 DataTable 接收
|
||||
</summary>
|
||||
<param name="properties">属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.ISelect0`2.ToDictionary``1(System.Func{`1,``0})">
|
||||
<summary>
|
||||
以字典的形式返回查询结果<para></para>
|
||||
@ -2922,6 +2967,13 @@
|
||||
<param name="tableRule"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IUpdate`1.AsTable(System.String)">
|
||||
<summary>
|
||||
设置表名
|
||||
</summary>
|
||||
<param name="tableName"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IUpdate`1.AsType(System.Type)">
|
||||
<summary>
|
||||
动态Type,在使用 Update<object> 后使用本方法,指定实体类型
|
||||
@ -4167,6 +4219,27 @@
|
||||
此时 Value 的值格式为逗号分割:value1,value2,value3... 或者数组
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.Model.DynamicFilterOperator.Custom">
|
||||
<summary>
|
||||
自定义解析,此时 Field 为反射信息,Value 为静态方法的参数(string)<para></para>
|
||||
示范:{ Operator: "Custom", Field: "RawSql webapp1.DynamicFilterCustom,webapp1", Value: "(id,name) in ((1,'k'),(2,'m'))" }<para></para>
|
||||
注意:使用者自己承担【注入风险】<para></para>
|
||||
静态方法定义示范:<para></para>
|
||||
namespace webapp1<para></para>
|
||||
{<para></para>
|
||||
public class DynamicFilterCustom<para></para>
|
||||
{<para></para>
|
||||
[DynamicFilterCustom]<para></para>
|
||||
public static string RawSql(string value) => value;<para></para>
|
||||
}<para></para>
|
||||
}<para></para>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:FreeSql.Internal.Model.DynamicFilterCustomAttribute">
|
||||
<summary>
|
||||
授权 DynamicFilter 支持 Custom 自定义解析
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Internal.Model.FetchCallbackArgs`1.IsBreak">
|
||||
<summary>
|
||||
是否放弃继续读取
|
||||
@ -4269,6 +4342,11 @@
|
||||
后台定时检查可用性间隔秒数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Internal.ObjectPool.IPolicy`1.Weight">
|
||||
<summary>
|
||||
权重
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnCreate">
|
||||
<summary>
|
||||
对象池的对象被创建时
|
||||
@ -4582,6 +4660,64 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.InsertDict(IFreeSql,System.Collections.Generic.Dictionary{System.String,System.Object})">
|
||||
<summary>
|
||||
插入数据字典 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.InsertDict(IFreeSql,System.Collections.Generic.IEnumerable{System.Collections.Generic.Dictionary{System.String,System.Object}})">
|
||||
<summary>
|
||||
插入数据字典,传入 Dictionary<string, object> 集合
|
||||
</summary>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.UpdateDict(IFreeSql,System.Collections.Generic.Dictionary{System.String,System.Object})">
|
||||
<summary>
|
||||
更新数据字典 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.UpdateDict(IFreeSql,System.Collections.Generic.IEnumerable{System.Collections.Generic.Dictionary{System.String,System.Object}})">
|
||||
<summary>
|
||||
更新数据字典,传入 Dictionary<string, object> 集合
|
||||
</summary>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.InsertOrUpdateDict(IFreeSql,System.Collections.Generic.Dictionary{System.String,System.Object})">
|
||||
<summary>
|
||||
插入或更新数据字典,此功能依赖数据库特性(低版本可能不支持),参考如下:<para></para>
|
||||
MySql 5.6+: on duplicate key update<para></para>
|
||||
PostgreSQL 9.4+: on conflict do update<para></para>
|
||||
SqlServer 2008+: merge into<para></para>
|
||||
Oracle 11+: merge into<para></para>
|
||||
Sqlite: replace into<para></para>
|
||||
达梦: merge into<para></para>
|
||||
人大金仓:on conflict do update<para></para>
|
||||
神通:merge into<para></para>
|
||||
MsAccess:不支持<para></para>
|
||||
</summary>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.DeleteDict(IFreeSql,System.Collections.Generic.Dictionary{System.String,System.Object})">
|
||||
<summary>
|
||||
删除数据字典 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.DeleteDict(IFreeSql,System.Collections.Generic.IEnumerable{System.Collections.Generic.Dictionary{System.String,System.Object}})">
|
||||
<summary>
|
||||
删除数据字典,传入 Dictionary<string, object> 集合
|
||||
</summary>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.And``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
|
||||
<summary>
|
||||
使用 and 拼接两个 lambda 表达式
|
||||
|
@ -14,6 +14,7 @@ namespace FreeSql
|
||||
DataType _dataType;
|
||||
string _masterConnectionString;
|
||||
string[] _slaveConnectionString;
|
||||
int[] _slaveWeights;
|
||||
Func<DbConnection> _connectionFactory;
|
||||
bool _isAutoSyncStructure = false;
|
||||
bool _isSyncStructureToLower = false;
|
||||
@ -55,6 +56,12 @@ namespace FreeSql
|
||||
_slaveConnectionString = slaveConnectionString;
|
||||
return this;
|
||||
}
|
||||
public FreeSqlBuilder UseSlaveWeight(params int[] slaveWeights)
|
||||
{
|
||||
if (_slaveConnectionString?.Length != slaveWeights.Length) throw new Exception("SlaveConnectionString 数量与 SlaveWeights 不相同");
|
||||
_slaveWeights = slaveWeights;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 使用自定义数据库连接对象(放弃内置对象连接池技术)
|
||||
/// </summary>
|
||||
@ -201,6 +208,7 @@ namespace FreeSql
|
||||
break;
|
||||
case DataType.Sqlite:
|
||||
type = Type.GetType("FreeSql.Sqlite.SqliteProvider`1,FreeSql.Provider.Sqlite")?.MakeGenericType(typeof(TMark));
|
||||
if (type == null) type = Type.GetType("FreeSql.Sqlite.SqliteProvider`1,FreeSql.Provider.SqliteCore")?.MakeGenericType(typeof(TMark)); //Microsoft.Data.Sqlite.Core.dll
|
||||
if (type == null) throwNotFind("FreeSql.Provider.Sqlite.dll", "FreeSql.Sqlite.SqliteProvider<>");
|
||||
break;
|
||||
|
||||
@ -265,6 +273,16 @@ namespace FreeSql
|
||||
if (type == null) throwNotFind("FreeSql.Provider.Custom.dll", "FreeSql.Custom.CustomProvider<>");
|
||||
break;
|
||||
|
||||
case DataType.ClickHouse:
|
||||
type = Type.GetType("FreeSql.ClickHouse.ClickHouseProvider`1,FreeSql.Provider.ClickHouse")?.MakeGenericType(typeof(TMark));
|
||||
if (type == null) throwNotFind("FreeSql.Provider.ClickHouse.dll", "FreeSql.ClickHouse.ClickHouseProvider<>");
|
||||
break;
|
||||
|
||||
case DataType.GBase:
|
||||
type = Type.GetType("FreeSql.GBase.GBaseProvider`1,FreeSql.Provider.GBase")?.MakeGenericType(typeof(TMark));
|
||||
if (type == null) throwNotFind("FreeSql.Provider.GBase.dll", "FreeSql.GBase.GBaseProvider<>");
|
||||
break;
|
||||
|
||||
default: throw new Exception("未指定 UseConnectionString 或者 UseConnectionFactory");
|
||||
}
|
||||
}
|
||||
@ -447,6 +465,9 @@ namespace FreeSql
|
||||
|
||||
ret.Ado.MasterPool.Policy.IsAutoDisposeWithSystem = _isExitAutoDisposePool;
|
||||
ret.Ado.SlavePools.ForEach(a => a.Policy.IsAutoDisposeWithSystem = _isExitAutoDisposePool);
|
||||
if (_slaveWeights != null)
|
||||
for (var x = 0; x < _slaveWeights.Length; x++)
|
||||
ret.Ado.SlavePools[x].Policy.Weight = _slaveWeights[x];
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -95,6 +95,12 @@ namespace FreeSql
|
||||
/// <returns></returns>
|
||||
IDelete<T1> AsTable(Func<string, string> tableRule);
|
||||
/// <summary>
|
||||
/// 设置表名
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <returns></returns>
|
||||
IDelete<T1> AsTable(string tableName);
|
||||
/// <summary>
|
||||
/// 动态Type,在使用 Delete<object> 后使用本方法,指定实体类型
|
||||
/// </summary>
|
||||
/// <param name="entityType"></param>
|
||||
|
@ -119,6 +119,12 @@ namespace FreeSql
|
||||
/// <returns></returns>
|
||||
IInsert<T1> AsTable(Func<string, string> tableRule);
|
||||
/// <summary>
|
||||
/// 设置表名
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <returns></returns>
|
||||
IInsert<T1> AsTable(string tableName);
|
||||
/// <summary>
|
||||
/// 动态Type,在使用 Insert<object> 后使用本方法,指定实体类型
|
||||
/// </summary>
|
||||
/// <param name="entityType"></param>
|
||||
|
@ -69,6 +69,12 @@ namespace FreeSql
|
||||
/// <returns></returns>
|
||||
IInsertOrUpdate<T1> AsTable(Func<string, string> tableRule);
|
||||
/// <summary>
|
||||
/// 设置表名
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <returns></returns>
|
||||
IInsertOrUpdate<T1> AsTable(string tableName);
|
||||
/// <summary>
|
||||
/// 动态Type,在使用 Update<object> 后使用本方法,指定实体类型
|
||||
/// </summary>
|
||||
/// <param name="entityType"></param>
|
||||
|
@ -18,6 +18,7 @@ namespace FreeSql
|
||||
#if net40
|
||||
#else
|
||||
Task<DataTable> ToDataTableAsync(string field = null, CancellationToken cancellationToken = default);
|
||||
Task<DataTable> ToDataTableByPropertyNameAsync(string[] properties, CancellationToken cancellationToken = default);
|
||||
Task<Dictionary<TKey, T1>> ToDictionaryAsync<TKey>(Func<T1, TKey> keySelector, CancellationToken cancellationToken = default);
|
||||
Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TKey, TElement>(Func<T1, TKey> keySelector, Func<T1, TElement> elementSelector, CancellationToken cancellationToken = default);
|
||||
Task<List<T1>> ToListAsync(bool includeNestedMembers = false, CancellationToken cancellationToken = default);
|
||||
@ -72,6 +73,12 @@ namespace FreeSql
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
DataTable ToDataTable(string field = null);
|
||||
/// <summary>
|
||||
/// 执行SQL查询,返回 properties 指定的实体类属性,并以 DataTable 接收
|
||||
/// </summary>
|
||||
/// <param name="properties">属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name</param>
|
||||
/// <returns></returns>
|
||||
DataTable ToDataTableByPropertyName(string[] properties);
|
||||
|
||||
/// <summary>
|
||||
/// 以字典的形式返回查询结果<para></para>
|
||||
|
@ -227,6 +227,12 @@ namespace FreeSql
|
||||
/// <returns></returns>
|
||||
IUpdate<T1> AsTable(Func<string, string> tableRule);
|
||||
/// <summary>
|
||||
/// 设置表名
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <returns></returns>
|
||||
IUpdate<T1> AsTable(string tableName);
|
||||
/// <summary>
|
||||
/// 动态Type,在使用 Update<object> 后使用本方法,指定实体类型
|
||||
/// </summary>
|
||||
/// <param name="entityType"></param>
|
||||
|
@ -591,6 +591,8 @@ namespace FreeSql.Internal
|
||||
if (rightExp.Type.NullableTypeOrThis() == typeof(TimeSpan))
|
||||
return ExpressionLambdaToSql(Expression.Call(leftExp, MethodDateTimeSubtractTimeSpan, rightExp), tsc);
|
||||
}
|
||||
if (oper == "OR")
|
||||
return $"({GetBoolString(ExpressionLambdaToSql(leftExp, tsc))} {oper} {GetBoolString(ExpressionLambdaToSql(rightExp, tsc))})";
|
||||
return $"({ExpressionLambdaToSql(leftExp, tsc)} {oper} {ExpressionLambdaToSql(rightExp, tsc)})";
|
||||
case "=":
|
||||
case "<>":
|
||||
@ -1011,6 +1013,7 @@ namespace FreeSql.Internal
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.Dameng:
|
||||
case DataType.OdbcDameng:
|
||||
case DataType.GBase:
|
||||
break;
|
||||
default:
|
||||
fsqlSelect0._limit = 1; //#462 ORACLE rownum <= 2 会影响索引变慢
|
||||
@ -1065,25 +1068,32 @@ namespace FreeSql.Internal
|
||||
else
|
||||
{
|
||||
var argExp = (arg3Exp as UnaryExpression)?.Operand;
|
||||
if (argExp != null && argExp.NodeType == ExpressionType.Lambda)
|
||||
if (argExp != null)
|
||||
{
|
||||
if (fsqltable1SetAlias == false)
|
||||
if (argExp.NodeType == ExpressionType.Lambda)
|
||||
{
|
||||
fsqltable1SetAlias = true;
|
||||
var argExpLambda = argExp as LambdaExpression;
|
||||
var fsqlTypeGenericArgs = fsqlType.GetGenericArguments();
|
||||
if (fsqltable1SetAlias == false)
|
||||
{
|
||||
fsqltable1SetAlias = true;
|
||||
var argExpLambda = argExp as LambdaExpression;
|
||||
var fsqlTypeGenericArgs = fsqlType.GetGenericArguments();
|
||||
|
||||
if (argExpLambda.Parameters.Count == 1 && argExpLambda.Parameters[0].Type.FullName.StartsWith("FreeSql.Internal.Model.HzyTuple`"))
|
||||
{
|
||||
for (var gai = 0; gai < fsqlTypeGenericArgs.Length; gai++)
|
||||
fsqltables[gai].Alias = "ht" + (gai + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var gai = 0; gai < fsqlTypeGenericArgs.Length && gai < argExpLambda.Parameters.Count; gai++)
|
||||
fsqltables[gai].Alias = argExpLambda.Parameters[gai].Name;
|
||||
if (argExpLambda.Parameters.Count == 1 && argExpLambda.Parameters[0].Type.FullName.StartsWith("FreeSql.Internal.Model.HzyTuple`"))
|
||||
{
|
||||
for (var gai = 0; gai < fsqlTypeGenericArgs.Length; gai++)
|
||||
fsqltables[gai].Alias = "ht" + (gai + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var gai = 0; gai < fsqlTypeGenericArgs.Length && gai < argExpLambda.Parameters.Count; gai++)
|
||||
fsqltables[gai].Alias = argExpLambda.Parameters[gai].Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
argExp = null;
|
||||
}
|
||||
}
|
||||
args[a] = argExp ?? Expression.Lambda(arg3Exp).Compile().DynamicInvoke();
|
||||
//if (args[a] == null) ExpressionLambdaToSql(call3Exp.Arguments[a], fsqltables, null, null, SelectTableInfoType.From, true);
|
||||
@ -1305,6 +1315,7 @@ namespace FreeSql.Internal
|
||||
{
|
||||
case DataType.MySql:
|
||||
case DataType.OdbcMySql:
|
||||
case DataType.GBase:
|
||||
if (exp3.Method.Name == "ToList")
|
||||
return $"( SELECT * FROM ({sqlFirst.Replace(" \r\n", " \r\n ")}) ftblmt50 )";
|
||||
break;
|
||||
@ -1876,10 +1887,14 @@ namespace FreeSql.Internal
|
||||
if (_common.CodeFirst.IsGenerateCommandParameterWithLambda && dbParams != null)
|
||||
{
|
||||
if (obj == null) return "NULL";
|
||||
var paramName = $"exp_{dbParams.Count}";
|
||||
var parm = _common.AppendParamter(dbParams, paramName, mapColumn,
|
||||
mapType ?? mapColumn?.Attribute.MapType ?? obj?.GetType(), mapType == null ? obj : Utils.GetDataReaderValue(mapType, obj));
|
||||
return _common.QuoteParamterName(paramName);
|
||||
var type = mapType ?? mapColumn?.Attribute.MapType ?? obj?.GetType();
|
||||
if (_common.CodeFirst.GetDbInfo(type) != null)
|
||||
{
|
||||
var paramName = $"exp_{dbParams.Count}";
|
||||
if (_common._orm?.Ado.DataType == DataType.GBase) paramName = "?";
|
||||
var parm = _common.AppendParamter(dbParams, paramName, mapColumn, type, mapType == null ? obj : Utils.GetDataReaderValue(mapType, obj));
|
||||
return _common.QuoteParamterName(paramName);
|
||||
}
|
||||
}
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0}", _ado.AddslashesProcessParam(obj, mapType, mapColumn));
|
||||
//return string.Concat(_ado.AddslashesProcessParam(obj, mapType, mapColumn));
|
||||
|
@ -111,6 +111,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
case DataType.Oracle:
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.GBase:
|
||||
ExecuteNonQuery(null, null, CommandType.Text, " SELECT 1 FROM dual", commandTimeout);
|
||||
return true;
|
||||
case DataType.Firebird:
|
||||
@ -581,7 +582,20 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (availables.Any())
|
||||
{
|
||||
isSlave = true;
|
||||
pool = availables.Count == 1 ? availables[0] : availables[slaveRandom.Next(availables.Count)];
|
||||
if (availables.Count == 1) pool = availables[0];
|
||||
else
|
||||
{
|
||||
var rnd = slaveRandom.Next(availables.Sum(a => a.Policy.Weight));
|
||||
for(var a = 0; a < availables.Count; a++)
|
||||
{
|
||||
rnd -= availables[a].Policy.Weight;
|
||||
if (rnd < 0)
|
||||
{
|
||||
pool = availables[a];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -851,6 +865,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
|
||||
if (cmdParms != null)
|
||||
{
|
||||
var dbpool = MasterPool as FreeSql.Internal.CommonProvider.DbConnectionPool;
|
||||
foreach (var parm in cmdParms)
|
||||
{
|
||||
if (parm == null) continue;
|
||||
@ -871,7 +886,32 @@ namespace FreeSql.Internal.CommonProvider
|
||||
});
|
||||
}
|
||||
}
|
||||
if (isnew == false) cmd.Parameters.Add(parm);
|
||||
if (isnew == false)
|
||||
{
|
||||
if (dbpool == null) cmd.Parameters.Add(parm);
|
||||
else
|
||||
{
|
||||
var newparm = cmd.CreateParameter(); // UseConnectionFactory 转换 DbParameter
|
||||
if (newparm.GetType() == parm.GetType()) cmd.Parameters.Add(parm);
|
||||
else
|
||||
{
|
||||
newparm.DbType = parm.DbType;
|
||||
newparm.Direction = parm.Direction;
|
||||
newparm.ParameterName = parm.ParameterName;
|
||||
#if net40 || net45
|
||||
#else
|
||||
newparm.Precision = parm.Precision;
|
||||
newparm.Scale = parm.Scale;
|
||||
#endif
|
||||
newparm.Size = parm.Size;
|
||||
newparm.SourceColumn = parm.SourceColumn;
|
||||
newparm.SourceColumnNullMapping = parm.SourceColumnNullMapping;
|
||||
newparm.SourceVersion = parm.SourceVersion;
|
||||
newparm.Value = parm.Value;
|
||||
cmd.Parameters.Add(newparm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
case DataType.Oracle:
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.GBase:
|
||||
await ExecuteNonQueryAsync(null, null, CommandType.Text, " SELECT 1 FROM dual", commandTimeout, null, cancellationToken);
|
||||
return true;
|
||||
case DataType.Firebird:
|
||||
@ -78,7 +79,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}, cmdType, cmdText, cmdTimeout, cmdParms, cancellationToken);
|
||||
return ret;
|
||||
}
|
||||
#region QueryAsync multi
|
||||
#region QueryAsync multi
|
||||
public Task<NativeTuple<List<T1>, List<T2>>> QueryAsync<T1, T2>(string cmdText, object parms = null, CancellationToken cancellationToken = default) => QueryAsync<T1, T2>(null, null, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
|
||||
public Task<NativeTuple<List<T1>, List<T2>>> QueryAsync<T1, T2>(DbTransaction transaction, string cmdText, object parms = null, CancellationToken cancellationToken = default) => QueryAsync<T1, T2>(null, transaction, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
|
||||
public Task<NativeTuple<List<T1>, List<T2>>> QueryAsync<T1, T2>(DbConnection connection, DbTransaction transaction, string cmdText, object parms = null, CancellationToken cancellationToken = default) => QueryAsync<T1, T2>(connection, transaction, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
|
||||
@ -468,7 +469,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}, null, cmdType, cmdText, cmdTimeout, cmdParms, cancellationToken);
|
||||
return NativeTuple.Create(ret1, ret2, ret3, ret4, ret5);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
public Task ExecuteReaderAsync(Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, string cmdText, object parms = null, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, null, fetchHandler, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
|
||||
public Task ExecuteReaderAsync(DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, string cmdText, object parms = null, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, transaction, fetchHandler, CommandType.Text, cmdText, 0, GetDbParamtersByObject(cmdText, parms), cancellationToken);
|
||||
@ -476,7 +477,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public Task ExecuteReaderAsync(Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, CommandType cmdType, string cmdText, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, null, fetchHandler, cmdType, cmdText, 0, cmdParms, cancellationToken);
|
||||
public Task ExecuteReaderAsync(DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, CommandType cmdType, string cmdText, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, transaction, fetchHandler, cmdType, cmdText, 0, cmdParms, cancellationToken);
|
||||
public Task ExecuteReaderAsync(DbConnection connection, DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, Task> fetchHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderMultipleAsync(1, connection, transaction, (fetch, result) => fetchHandler(fetch), null, cmdType, cmdText, cmdTimeout, cmdParms, cancellationToken);
|
||||
public async Task ExecuteReaderMultipleAsync(int multipleResult, DbConnection connection, DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, int, Task> fetchHandler, Action<DbDataReader, int> schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default)
|
||||
async public Task ExecuteReaderMultipleAsync(int multipleResult, DbConnection connection, DbTransaction transaction, Func<FetchCallbackArgs<DbDataReader>, int, Task> fetchHandler, Action<DbDataReader, int> schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrEmpty(cmdText)) return;
|
||||
var dt = DateTime.Now;
|
||||
@ -756,6 +757,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
|
||||
if (cmdParms != null)
|
||||
{
|
||||
var dbpool = MasterPool as FreeSql.Internal.CommonProvider.DbConnectionPool;
|
||||
foreach (var parm in cmdParms)
|
||||
{
|
||||
if (parm == null) continue;
|
||||
@ -776,7 +778,32 @@ namespace FreeSql.Internal.CommonProvider
|
||||
});
|
||||
}
|
||||
}
|
||||
if (isnew == false) cmd.Parameters.Add(parm);
|
||||
if (isnew == false)
|
||||
{
|
||||
if (dbpool == null) cmd.Parameters.Add(parm);
|
||||
else
|
||||
{
|
||||
var newparm = cmd.CreateParameter(); // UseConnectionFactory 转换 DbParameter
|
||||
if (newparm.GetType() == parm.GetType()) cmd.Parameters.Add(parm);
|
||||
else
|
||||
{
|
||||
newparm.DbType = parm.DbType;
|
||||
newparm.Direction = parm.Direction;
|
||||
newparm.ParameterName = parm.ParameterName;
|
||||
#if net40 || net45
|
||||
#else
|
||||
newparm.Precision = parm.Precision;
|
||||
newparm.Scale = parm.Scale;
|
||||
#endif
|
||||
newparm.Size = parm.Size;
|
||||
newparm.SourceColumn = parm.SourceColumn;
|
||||
newparm.SourceColumnNullMapping = parm.SourceColumnNullMapping;
|
||||
newparm.SourceVersion = parm.SourceVersion;
|
||||
newparm.Value = parm.Value;
|
||||
cmd.Parameters.Add(newparm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public bool IsThrowGetTimeoutException { get; set; } = true;
|
||||
public bool IsAutoDisposeWithSystem { get; set; } = true;
|
||||
public int CheckAvailableInterval { get; set; } = 5;
|
||||
public int Weight { get; set; } = 1;
|
||||
|
||||
public DbConnection OnCreate()
|
||||
{
|
||||
|
@ -15,7 +15,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
|
||||
public ISelect<T1> Select<T1>() where T1 : class => CreateSelectProvider<T1>(null);
|
||||
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => CreateSelectProvider<T1>(dywhere);
|
||||
public IInsert<T1> Insert<T1>() where T1 : class => CreateInsertProvider<T1>();
|
||||
public IInsert<T1> Insert<T1>() where T1 : class
|
||||
{
|
||||
if (typeof(T1) == typeof(Dictionary<string, object>)) throw new Exception("请使用 fsql.InsertDict(dict) 方法插入字典数据");
|
||||
return CreateInsertProvider<T1>();
|
||||
}
|
||||
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>(List<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||
|
@ -94,7 +94,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
protected void SyncStructure(params TypeAndName[] objects)
|
||||
{
|
||||
if (objects == null) return;
|
||||
var syncObjects = objects.Where(a => a.entityType != typeof(object) && _dicSycedGetOrAdd(a.entityType).ContainsKey(GetTableNameLowerOrUpper(a.tableName)) == false && GetTableByEntity(a.entityType)?.DisableSyncStructure == false)
|
||||
var syncObjects = objects.Where(a => a.entityType != null && a.entityType != typeof(object) && _dicSycedGetOrAdd(a.entityType).ContainsKey(GetTableNameLowerOrUpper(a.tableName)) == false && GetTableByEntity(a.entityType)?.DisableSyncStructure == false)
|
||||
.Select(a => new TypeAndName(a.entityType, GetTableNameLowerOrUpper(a.tableName))).ToArray();
|
||||
if (syncObjects.Any() == false) return;
|
||||
var before = new Aop.SyncStructureBeforeEventArgs(syncObjects.Select(a => a.entityType).ToArray());
|
||||
|
@ -147,6 +147,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_tableRule = tableRule;
|
||||
return this;
|
||||
}
|
||||
public IDelete<T1> AsTable(string tableName)
|
||||
{
|
||||
_tableRule = (oldname) => tableName;
|
||||
return this;
|
||||
}
|
||||
public IDelete<T1> AsType(Type entityType)
|
||||
{
|
||||
if (entityType == typeof(object)) throw new Exception("IDelete.AsType 参数不支持指定为 object");
|
||||
@ -157,7 +162,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
return this;
|
||||
}
|
||||
|
||||
public string ToSql()
|
||||
public virtual string ToSql()
|
||||
{
|
||||
if (_whereTimes <= 0) return null;
|
||||
var sb = new StringBuilder().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" WHERE ").Append(_where);
|
||||
|
@ -29,7 +29,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public DbTransaction _transaction;
|
||||
public DbConnection _connection;
|
||||
public int _commandTimeout = 0;
|
||||
public ColumnInfo IdentityColumn { get; }
|
||||
public ColumnInfo IdentityColumn { get; private set; }
|
||||
|
||||
public InsertOrUpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
|
||||
{
|
||||
@ -37,12 +37,10 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_commonUtils = commonUtils;
|
||||
_commonExpression = commonExpression;
|
||||
_table = _commonUtils.GetTableByEntity(typeof(T1));
|
||||
if (_table == null)
|
||||
{
|
||||
if (_table == null && typeof(T1) != typeof(Dictionary<string, object>))
|
||||
throw new Exception($"InsertOrUpdate<>的泛型参数 不支持 {typeof(T1)},请传递您的实体类");
|
||||
}
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
IdentityColumn = _table.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault();
|
||||
IdentityColumn = _table?.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault();
|
||||
}
|
||||
|
||||
protected void ClearData()
|
||||
@ -88,14 +86,14 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
|
||||
{
|
||||
if (data == null) return;
|
||||
if (data == null || table == null) return;
|
||||
if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
|
||||
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
|
||||
if (orm.Aop.AuditValueHandler == null) return;
|
||||
foreach (var col in table.Columns.Values)
|
||||
{
|
||||
object val = col.GetValue(data);
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.InsertOrUpdate, col, table.Properties[col.CsName], val);
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.InsertOrUpdate, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
|
||||
orm.Aop.AuditValueHandler(sender, auditArgs);
|
||||
if (auditArgs.ValueIsChanged)
|
||||
{
|
||||
@ -112,6 +110,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public IInsertOrUpdate<T1> SetSource(IEnumerable<T1> source)
|
||||
{
|
||||
if (source == null || source.Any() == false) return this;
|
||||
UpdateProvider<T1>.GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
|
||||
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
|
||||
_source.AddRange(source.Where(a => a != null));
|
||||
return this;
|
||||
@ -139,6 +138,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_tableRule = tableRule;
|
||||
return this;
|
||||
}
|
||||
public IInsertOrUpdate<T1> AsTable(string tableName)
|
||||
{
|
||||
_tableRule = (oldname) => tableName;
|
||||
return this;
|
||||
}
|
||||
public IInsertOrUpdate<T1> AsType(Type entityType)
|
||||
{
|
||||
if (entityType == typeof(object)) throw new Exception("IInsertOrUpdate.AsType 参数不支持指定为 object");
|
||||
@ -146,6 +150,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var newtb = _commonUtils.GetTableByEntity(entityType);
|
||||
_table = newtb ?? throw new Exception("IInsertOrUpdate.AsType 参数错误,请传入正确的实体类型");
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
|
||||
IdentityColumn = _table.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault();
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -182,6 +187,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
case DataType.Oracle:
|
||||
case DataType.OdbcDameng:
|
||||
case DataType.Dameng:
|
||||
case DataType.GBase:
|
||||
sb.Append(" FROM dual");
|
||||
break;
|
||||
case DataType.Firebird:
|
||||
|
@ -9,6 +9,7 @@ using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
|
||||
namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
@ -115,6 +116,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
if (source != null)
|
||||
{
|
||||
UpdateProvider<T1>.GetDictionaryTableInfo(source, _orm, ref _table);
|
||||
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
|
||||
_source.Add(source);
|
||||
}
|
||||
@ -124,6 +126,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
if (source != null)
|
||||
{
|
||||
UpdateProvider<T1>.GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
|
||||
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
|
||||
_source.AddRange(source);
|
||||
}
|
||||
@ -134,6 +137,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (source != null)
|
||||
{
|
||||
source = source.Where(a => a != null).ToList();
|
||||
UpdateProvider<T1>.GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
|
||||
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
|
||||
_source.AddRange(source);
|
||||
|
||||
@ -148,7 +152,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
|
||||
{
|
||||
if (data == null) return;
|
||||
if (data == null || table == null) return;
|
||||
if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
|
||||
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
|
||||
foreach (var col in table.Columns.Values)
|
||||
@ -156,7 +160,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
object val = col.GetValue(data);
|
||||
if (orm.Aop.AuditValueHandler != null)
|
||||
{
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Insert, col, table.Properties[col.CsName], val);
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Insert, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
|
||||
orm.Aop.AuditValueHandler(sender, auditArgs);
|
||||
if (auditArgs.ValueIsChanged)
|
||||
{
|
||||
@ -210,7 +214,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax));
|
||||
return ret;
|
||||
}
|
||||
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
|
||||
protected virtual int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
var ret = 0;
|
||||
@ -505,13 +509,14 @@ namespace FreeSql.Internal.CommonProvider
|
||||
|
||||
protected string TableRuleInvoke()
|
||||
{
|
||||
if (_tableRule == null) return _table.DbName;
|
||||
var newname = _tableRule(_table.DbName);
|
||||
if (newname == _table.DbName) return _table.DbName;
|
||||
if (string.IsNullOrEmpty(newname)) return _table.DbName;
|
||||
var tbname = _table?.DbName ?? "";
|
||||
if (_tableRule == null) return tbname;
|
||||
var newname = _tableRule(tbname);
|
||||
if (newname == tbname) return tbname;
|
||||
if (string.IsNullOrEmpty(newname)) return tbname;
|
||||
if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower();
|
||||
if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper();
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname);
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table?.Type, newname);
|
||||
return newname;
|
||||
}
|
||||
public IInsert<T1> AsTable(Func<string, string> tableRule)
|
||||
@ -519,6 +524,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_tableRule = tableRule;
|
||||
return this;
|
||||
}
|
||||
public IInsert<T1> AsTable(string tableName)
|
||||
{
|
||||
_tableRule = (oldname) => tableName;
|
||||
return this;
|
||||
}
|
||||
public IInsert<T1> AsType(Type entityType)
|
||||
{
|
||||
if (entityType == typeof(object)) throw new Exception("IInsert.AsType 参数不支持指定为 object");
|
||||
|
@ -17,7 +17,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
#if net40
|
||||
#else
|
||||
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
async protected virtual Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
var ret = 0;
|
||||
@ -96,7 +96,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
return ret;
|
||||
}
|
||||
|
||||
async protected Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
async protected virtual Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
long ret = 0;
|
||||
@ -177,7 +177,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
return ret;
|
||||
}
|
||||
|
||||
async protected Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
async protected virtual Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
var ret = new List<T1>();
|
||||
|
@ -352,6 +352,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
case DataType.Oracle:
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.Firebird:
|
||||
case DataType.GBase:
|
||||
break;
|
||||
default:
|
||||
_select = "SELECT ";
|
||||
@ -407,6 +408,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
case DataType.Oracle:
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.Firebird:
|
||||
case DataType.GBase:
|
||||
break;
|
||||
default:
|
||||
var beforeSql = this._select;
|
||||
@ -440,6 +442,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
case DataType.Oracle:
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.Firebird:
|
||||
case DataType.GBase:
|
||||
break;
|
||||
default:
|
||||
var beforeSql = this._select;
|
||||
@ -544,17 +547,35 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
if (string.IsNullOrEmpty(fi.Field) == false)
|
||||
{
|
||||
Expression exp = ConvertStringPropertyToExpression(fi.Field);
|
||||
Expression exp = null;
|
||||
switch (fi.Operator)
|
||||
{
|
||||
case DynamicFilterOperator.Custom:
|
||||
var fiValueCustomArray = fi.Field?.ToString().Split(new[] { ' ' }, 2);
|
||||
if (fiValueCustomArray.Length != 2) throw new ArgumentException("Custom 要求 Field 应该空格分割,并且长度为 2,格式:{静态方法名}{空格}{反射信息}");
|
||||
if (string.IsNullOrWhiteSpace(fiValueCustomArray[0])) throw new ArgumentException("Custom {静态方法名}不能为空,格式:{静态方法名}{空格}{反射信息}");
|
||||
if (string.IsNullOrWhiteSpace(fiValueCustomArray[1])) throw new ArgumentException("Custom {反射信息}不能为空,格式:{静态方法名}{空格}{反射信息}");
|
||||
var fiValue1Type = Type.GetType(fiValueCustomArray[1]);
|
||||
if (fiValue1Type == null) throw new ArgumentException($"Custom 找不到对应的{{反射信息}}:{fiValueCustomArray[1]}");
|
||||
var fiValue0Method = fiValue1Type.GetMethod(fiValueCustomArray[0], new Type[] { typeof(string) });
|
||||
if (fiValue0Method == null) throw new ArgumentException($"Custom 找不到对应的{{静态方法名}}:{fiValueCustomArray[0]}");
|
||||
if (MethodIsDynamicFilterCustomAttribute(fiValue0Method) == false) throw new ArgumentException($"Custom 对应的{{静态方法名}}:{fiValueCustomArray[0]} 未设置 [DynamicFilterCustomAttribute] 特性");
|
||||
var fiValue0MethodReturn = fiValue0Method?.Invoke(null, new object[] { fi.Value?.ToString() })?.ToString();
|
||||
exp = Expression.Call(typeof(SqlExt).GetMethod("InternalRawSql", BindingFlags.NonPublic | BindingFlags.Static), Expression.Constant(fiValue0MethodReturn, typeof(string)));
|
||||
break;
|
||||
|
||||
case DynamicFilterOperator.Contains:
|
||||
case DynamicFilterOperator.StartsWith:
|
||||
case DynamicFilterOperator.EndsWith:
|
||||
case DynamicFilterOperator.NotContains:
|
||||
case DynamicFilterOperator.NotStartsWith:
|
||||
case DynamicFilterOperator.NotEndsWith:
|
||||
exp = ConvertStringPropertyToExpression(fi.Field);
|
||||
if (exp.Type != typeof(string)) exp = Expression.TypeAs(exp, typeof(string));
|
||||
break;
|
||||
default:
|
||||
exp = ConvertStringPropertyToExpression(fi.Field);
|
||||
break;
|
||||
}
|
||||
switch (fi.Operator)
|
||||
{
|
||||
@ -579,7 +600,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (fiValueRangeArray.Length != 2) throw new ArgumentException($"Range 要求 Value 应该逗号分割,并且长度为 2");
|
||||
exp = Expression.AndAlso(
|
||||
Expression.GreaterThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[0]), exp.Type)),
|
||||
Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[1]), exp.Type)));
|
||||
Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[1]), exp.Type)));
|
||||
break;
|
||||
case DynamicFilterOperator.DateRange:
|
||||
var fiValueDateRangeArray = getFiListValue();
|
||||
@ -676,6 +697,21 @@ namespace FreeSql.Internal.CommonProvider
|
||||
string.IsNullOrEmpty(testFilter.Value?.ToString());
|
||||
}
|
||||
}
|
||||
static ConcurrentDictionary<MethodInfo, bool> _dicMethodIsDynamicFilterCustomAttribute = new ConcurrentDictionary<MethodInfo, bool>();
|
||||
static bool MethodIsDynamicFilterCustomAttribute(MethodInfo method) => _dicMethodIsDynamicFilterCustomAttribute.GetOrAdd(method, m =>
|
||||
{
|
||||
object[] attrs = null;
|
||||
try
|
||||
{
|
||||
attrs = m.GetCustomAttributes(false).ToArray(); //.net core 反射存在版本冲突问题,导致该方法异常
|
||||
}
|
||||
catch { }
|
||||
|
||||
var dyattr = attrs?.Where(a => {
|
||||
return ((a as Attribute)?.TypeId as Type)?.Name == "DynamicFilterCustomAttribute";
|
||||
}).FirstOrDefault();
|
||||
return dyattr != null;
|
||||
});
|
||||
|
||||
public TSelect DisableGlobalFilter(params string[] name)
|
||||
{
|
||||
@ -722,6 +758,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
break;
|
||||
case DataType.Sqlite:
|
||||
break;
|
||||
case DataType.GBase:
|
||||
case DataType.ShenTong: //神通测试中发现,不支持 nowait
|
||||
_tosqlAppendContent = $"{_tosqlAppendContent} for update";
|
||||
break;
|
||||
|
@ -19,6 +19,25 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
partial class Select0Provider<TSelect, T1>
|
||||
{
|
||||
public DataTable ToDataTableByPropertyName(string[] properties)
|
||||
{
|
||||
if (properties?.Any() != true) throw new ArgumentException($"properties 参数不能为空");
|
||||
var sbfield = new StringBuilder();
|
||||
for (var propIdx = 0; propIdx < properties.Length; propIdx++)
|
||||
{
|
||||
var property = properties[propIdx];
|
||||
var exp = ConvertStringPropertyToExpression(property);
|
||||
if (exp == null) throw new Exception($"{property} 属性名无法找到");
|
||||
var field = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null);
|
||||
if (propIdx > 0) sbfield.Append(", ");
|
||||
sbfield.Append(field);
|
||||
//if (field != property)
|
||||
sbfield.Append(_commonUtils.FieldAsAlias(_commonUtils.QuoteSqlName("test").Replace("test", property)));
|
||||
}
|
||||
var sbfieldStr = sbfield.ToString();
|
||||
sbfield.Clear();
|
||||
return ToDataTable(sbfieldStr);
|
||||
}
|
||||
public DataTable ToDataTable(string field = null)
|
||||
{
|
||||
DataTable ret = null;
|
||||
@ -514,7 +533,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
});
|
||||
}
|
||||
static EventHandler<Aop.AuditDataReaderEventArgs> _OldAuditDataReaderHandler;
|
||||
public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2()
|
||||
public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2(bool isRereadSql = true)
|
||||
{
|
||||
if (_selectExpression != null) //ToSql
|
||||
{
|
||||
@ -530,7 +549,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_OldAuditDataReaderHandler = _orm.Aop.AuditDataReaderHandler; //清除单表 ExppressionTree
|
||||
_dicGetAllFieldExpressionTree.TryRemove($"{_orm.Ado.DataType}-{_tables[0].Table.DbName}-{_tables[0].Table.Type.FullName}-{_tables[0].Alias}-{_tables[0].Type}", out var oldet);
|
||||
}
|
||||
return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Table.Type.FullName}-{a.Alias}-{a.Type}")), s =>
|
||||
return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Table.Type.FullName}-{a.Alias}-{a.Type}-{(isRereadSql ? 1 : 0)}")), s =>
|
||||
{
|
||||
var tb1 = _tables.First().Table;
|
||||
var type = tb1.TypeLazy ?? tb1.Type;
|
||||
@ -564,7 +583,8 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{ //普通字段
|
||||
if (index > 0) field.Append(", ");
|
||||
var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
|
||||
field.Append(_commonUtils.RereadColumn(col, $"{tb.Alias}.{quoteName}"));
|
||||
if (isRereadSql) field.Append(_commonUtils.RereadColumn(col, $"{tb.Alias}.{quoteName}"));
|
||||
else field.Append($"{tb.Alias}.{quoteName}");
|
||||
++index;
|
||||
if (dicfield.ContainsKey(quoteName)) field.Append(_commonUtils.FieldAsAlias($"as{index}"));
|
||||
else dicfield.Add(quoteName, true);
|
||||
@ -587,7 +607,8 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
if (index > 0) field.Append(", ");
|
||||
var quoteName = _commonUtils.QuoteSqlName(col2.Attribute.Name);
|
||||
field.Append(_commonUtils.RereadColumn(col2, $"{tb2.Alias}.{quoteName}"));
|
||||
if (isRereadSql) field.Append(_commonUtils.RereadColumn(col2, $"{tb2.Alias}.{quoteName}"));
|
||||
else field.Append($"{tb2.Alias}.{quoteName}");
|
||||
++index;
|
||||
++otherindex;
|
||||
if (dicfield.ContainsKey(quoteName)) field.Append(_commonUtils.FieldAsAlias($"as{index}"));
|
||||
@ -760,8 +781,32 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null, _whereGlobalFilter);
|
||||
return this as TSelect;
|
||||
}
|
||||
protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null));
|
||||
protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
|
||||
protected TSelect InternalOrderBy(Expression column)
|
||||
{
|
||||
if (column.NodeType == ExpressionType.Lambda) column = (column as LambdaExpression)?.Body;
|
||||
switch (column?.NodeType)
|
||||
{
|
||||
case ExpressionType.New:
|
||||
var newExp = column as NewExpression;
|
||||
if (newExp == null) break;
|
||||
for (var a = 0; a < newExp.Members.Count; a++) this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], true, null));
|
||||
return this as TSelect;
|
||||
}
|
||||
return this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null));
|
||||
}
|
||||
protected TSelect InternalOrderByDescending(Expression column)
|
||||
{
|
||||
if (column.NodeType == ExpressionType.Lambda) column = (column as LambdaExpression)?.Body;
|
||||
switch (column?.NodeType)
|
||||
{
|
||||
case ExpressionType.New:
|
||||
var newExp = column as NewExpression;
|
||||
if (newExp == null) break;
|
||||
for (var a = 0; a < newExp.Members.Count; a++) this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], true, null)} DESC");
|
||||
return this as TSelect;
|
||||
}
|
||||
return this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
|
||||
}
|
||||
|
||||
public List<TReturn> InternalToList<TReturn>(Expression select) => this.ToListMapReader<TReturn>(this.GetExpressionField(select));
|
||||
protected string InternalToSql<TReturn>(Expression select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
|
||||
@ -876,6 +921,25 @@ namespace FreeSql.Internal.CommonProvider
|
||||
#region Async
|
||||
#if net40
|
||||
#else
|
||||
public Task<DataTable> ToDataTableByPropertyNameAsync(string[] properties, CancellationToken cancellationToken)
|
||||
{
|
||||
if (properties?.Any() != true) throw new ArgumentException($"properties 参数不能为空");
|
||||
var sbfield = new StringBuilder();
|
||||
for (var propIdx = 0; propIdx < properties.Length; propIdx++)
|
||||
{
|
||||
var property = properties[propIdx];
|
||||
var exp = ConvertStringPropertyToExpression(property);
|
||||
if (exp == null) throw new Exception($"{property} 属性名无法找到");
|
||||
var field = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null);
|
||||
if (propIdx > 0) sbfield.Append(", ");
|
||||
sbfield.Append(field);
|
||||
//if (field != property)
|
||||
sbfield.Append(_commonUtils.FieldAsAlias(_commonUtils.QuoteSqlName("test").Replace("test", property)));
|
||||
}
|
||||
var sbfieldStr = sbfield.ToString();
|
||||
sbfield.Clear();
|
||||
return ToDataTableAsync(sbfieldStr, cancellationToken);
|
||||
}
|
||||
async public Task<DataTable> ToDataTableAsync(string field, CancellationToken cancellationToken)
|
||||
{
|
||||
DataTable ret = null;
|
||||
|
@ -96,6 +96,15 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
public void InternalOrderBy(Expression exp, bool isDescending)
|
||||
{
|
||||
if (exp.NodeType == ExpressionType.Lambda) exp = (exp as LambdaExpression)?.Body;
|
||||
if (exp?.NodeType == ExpressionType.New)
|
||||
{
|
||||
var newExp = exp as NewExpression;
|
||||
if (newExp != null)
|
||||
for (var a = 0; a < newExp.Members.Count; a++)
|
||||
InternalOrderBy(newExp.Arguments[a], isDescending);
|
||||
return;
|
||||
}
|
||||
var sql = _comonExp.ExpressionWhereLambda(null, exp, this, null, null);
|
||||
var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
|
||||
method.Invoke(_select, new object[] { isDescending ? $"{sql} DESC" : sql, null });
|
||||
@ -150,6 +159,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.Dameng:
|
||||
case DataType.OdbcDameng: //Oracle、Dameng 分组时,嵌套分页
|
||||
case DataType.GBase:
|
||||
isNestedPageSql = true;
|
||||
break;
|
||||
default:
|
||||
|
@ -46,7 +46,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_commonUtils = commonUtils;
|
||||
_commonExpression = commonExpression;
|
||||
_table = _commonUtils.GetTableByEntity(typeof(T1));
|
||||
_tempPrimarys = _table.Primarys;
|
||||
_tempPrimarys = _table?.Primarys ?? new ColumnInfo[0];
|
||||
_noneParameter = _orm.CodeFirst.IsNoneCommandParameter;
|
||||
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
@ -60,7 +60,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
protected void IgnoreCanUpdate()
|
||||
{
|
||||
if (_table == null || _table.Type == typeof(object)) return;
|
||||
foreach (var col in _table.Columns.Values)
|
||||
foreach (var col in _table?.Columns.Values)
|
||||
if (col.Attribute.CanUpdate == false && _ignore.ContainsKey(col.Attribute.Name) == false)
|
||||
_ignore.Add(col.Attribute.Name, true);
|
||||
}
|
||||
@ -138,7 +138,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
|
||||
#region 参数化数据限制,或values数量限制
|
||||
internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit)
|
||||
protected internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit)
|
||||
{
|
||||
valuesLimit = valuesLimit - 1;
|
||||
parameterLimit = parameterLimit - 1;
|
||||
@ -163,7 +163,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax));
|
||||
return ret;
|
||||
}
|
||||
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
|
||||
protected virtual int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
var ret = 0;
|
||||
@ -237,7 +237,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit)
|
||||
protected virtual List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
var ret = new List<T1>();
|
||||
@ -377,7 +377,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
foreach (var col in table.Columns.Values)
|
||||
{
|
||||
object val = col.GetValue(d);
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val);
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
|
||||
orm.Aop.AuditValueHandler(sender, auditArgs);
|
||||
if (auditArgs.ValueIsChanged)
|
||||
{
|
||||
@ -393,13 +393,13 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
|
||||
{
|
||||
if (orm.Aop.AuditValueHandler == null) return;
|
||||
if (data == null) return;
|
||||
if (data == null || table == null) return;
|
||||
if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
|
||||
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
|
||||
foreach (var col in table.Columns.Values)
|
||||
{
|
||||
object val = col.GetValue(data);
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties[col.CsName], val);
|
||||
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.Update, col, table.Properties.TryGetValue(col.CsName, out var tryprop) ? tryprop : null, val);
|
||||
orm.Aop.AuditValueHandler(sender, auditArgs);
|
||||
if (auditArgs.ValueIsChanged)
|
||||
{
|
||||
@ -412,10 +412,49 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetDictionaryTableInfo(T1 source, IFreeSql orm, ref TableInfo table)
|
||||
{
|
||||
if (table == null && typeof(T1) == typeof(Dictionary<string, object>))
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException(nameof(source));
|
||||
var dic = source as Dictionary<string, object>;
|
||||
table = new TableInfo();
|
||||
table.Type = typeof(Dictionary<string, object>);
|
||||
table.CsName = dic.TryGetValue("", out var tryval) ? string.Concat(tryval) : "";
|
||||
table.DbName = table.CsName;
|
||||
table.DisableSyncStructure = true;
|
||||
table.IsDictionaryType = true;
|
||||
var colpos = new List<ColumnInfo>();
|
||||
foreach (var kv in dic)
|
||||
{
|
||||
var colName = kv.Key;
|
||||
if (orm.CodeFirst.IsSyncStructureToLower) colName = colName.ToLower();
|
||||
if (orm.CodeFirst.IsSyncStructureToUpper) colName = colName.ToUpper();
|
||||
var col = new ColumnInfo
|
||||
{
|
||||
CsName = kv.Key,
|
||||
Table = table,
|
||||
Attribute = new DataAnnotations.ColumnAttribute
|
||||
{
|
||||
Name = colName,
|
||||
MapType = typeof(object)
|
||||
},
|
||||
CsType = typeof(object)
|
||||
};
|
||||
table.Columns.Add(colName, col);
|
||||
table.ColumnsByCs.Add(kv.Key, col);
|
||||
colpos.Add(col);
|
||||
}
|
||||
table.ColumnsByPosition = colpos.ToArray();
|
||||
colpos.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public IUpdate<T1> SetSource(T1 source) => this.SetSource(new[] { source });
|
||||
public IUpdate<T1> SetSource(IEnumerable<T1> source, Expression<Func<T1, object>> tempPrimarys = null)
|
||||
{
|
||||
if (source == null || source.Any() == false) return this;
|
||||
GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table);
|
||||
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
|
||||
_source.AddRange(source.Where(a => a != null));
|
||||
|
||||
@ -445,7 +484,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_set.Append(", ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
|
||||
|
||||
var colsql = _noneParameter ? _commonUtils.GetNoneParamaterSqlValue(_params, "u", col, col.Attribute.MapType, val) :
|
||||
_commonUtils.QuoteWriteParamterAdapter(col.Attribute.MapType, $"{_commonUtils.QuoteParamterName("p_")}{_params.Count}");
|
||||
_commonUtils.QuoteWriteParamterAdapter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_params.Count}"));
|
||||
_set.Append(_commonUtils.RewriteColumn(col, colsql));
|
||||
if (_noneParameter == false)
|
||||
_commonUtils.AppendParamter(_params, null, col, col.Attribute.MapType, val);
|
||||
@ -487,7 +526,8 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var memberName = initExp.Bindings[a].Member.Name;
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(memberName)) continue;
|
||||
if (_table.ColumnsByCs.TryGetValue(memberName, out var col) == false) throw new Exception($"找不到属性:{memberName}");
|
||||
var memberValue = _commonExpression.ExpressionLambdaToSql(initAssignExp.Expression, new CommonExpression.ExpTSC { isQuoteName = true, mapType = col.Attribute.MapType });
|
||||
var memberValue = _commonExpression.ExpressionLambdaToSql(initAssignExp.Expression, new CommonExpression.ExpTSC { isQuoteName = true,
|
||||
mapType = initAssignExp.Expression is BinaryExpression ? null : col.Attribute.MapType });
|
||||
_setIncr.Append(", ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(memberValue);
|
||||
}
|
||||
}
|
||||
@ -501,7 +541,8 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var memberName = newExp.Members[a].Name;
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(memberName)) continue;
|
||||
if (_table.ColumnsByCs.TryGetValue(memberName, out var col) == false) throw new Exception($"找不到属性:{memberName}");
|
||||
var memberValue = _commonExpression.ExpressionLambdaToSql(newExp.Arguments[a], new CommonExpression.ExpTSC { isQuoteName = true, mapType = col.Attribute.MapType });
|
||||
var memberValue = _commonExpression.ExpressionLambdaToSql(newExp.Arguments[a], new CommonExpression.ExpTSC { isQuoteName = true,
|
||||
mapType = newExp.Arguments[a] is BinaryExpression ? null : col.Attribute.MapType });
|
||||
_setIncr.Append(", ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(memberValue);
|
||||
}
|
||||
}
|
||||
@ -665,6 +706,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_tableRule = tableRule;
|
||||
return this;
|
||||
}
|
||||
public IUpdate<T1> AsTable(string tableName)
|
||||
{
|
||||
_tableRule = (oldname) => tableName;
|
||||
return this;
|
||||
}
|
||||
public IUpdate<T1> AsType(Type entityType)
|
||||
{
|
||||
if (entityType == typeof(object)) throw new Exception("IUpdate.AsType 参数不支持指定为 object");
|
||||
|
@ -18,7 +18,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
#if net40
|
||||
#else
|
||||
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
async protected virtual Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
var ret = 0;
|
||||
@ -91,7 +91,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
ClearData();
|
||||
return ret;
|
||||
}
|
||||
async protected Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
async protected virtual Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var ss = SplitSource(valuesLimit, parameterLimit);
|
||||
var ret = new List<T1>();
|
||||
|
@ -54,7 +54,7 @@ namespace FreeSql.Internal
|
||||
public abstract string NowUtc { get; }
|
||||
public abstract string QuoteWriteParamterAdapter(Type type, string paramterName);
|
||||
protected abstract string QuoteReadColumnAdapter(Type type, Type mapType, string columnName);
|
||||
public string RewriteColumn(ColumnInfo col, string sql)
|
||||
public virtual string RewriteColumn(ColumnInfo col, string sql)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(col?.Attribute.RewriteSql) == false)
|
||||
return string.Format(col.Attribute.RewriteSql, sql);
|
||||
|
@ -31,6 +31,7 @@ namespace FreeSql.Internal.Model
|
||||
/// <returns></returns>
|
||||
public object GetDbValue(object obj)
|
||||
{
|
||||
if (Table.IsDictionaryType) return (obj as Dictionary<string, object>)?.TryGetValue(CsName, out var tryval) == true ? tryval : null;
|
||||
var dbval = Table.GetPropertyValue(obj, CsName);
|
||||
//if (ConversionCsToDb != null) dbval = ConversionCsToDb(dbval);
|
||||
if (Attribute.MapType != CsType) dbval = Utils.GetDataReaderValue(Attribute.MapType, dbval);
|
||||
@ -40,13 +41,27 @@ namespace FreeSql.Internal.Model
|
||||
/// 获取 obj.CsName 属性原始值(不经过 MapType)
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
public object GetValue(object obj) => Table.GetPropertyValue(obj, CsName);
|
||||
public object GetValue(object obj)
|
||||
{
|
||||
if (Table.IsDictionaryType) return (obj as Dictionary<string, object>)?.TryGetValue(CsName, out var tryval) == true ? tryval : null;
|
||||
return Table.GetPropertyValue(obj, CsName);
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置 obj.CsName 属性值
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="val"></param>
|
||||
public void SetValue(object obj, object val) => Table.SetPropertyValue(obj, CsName, Utils.GetDataReaderValue(CsType, val));
|
||||
public void SetValue(object obj, object val)
|
||||
{
|
||||
if (Table.IsDictionaryType)
|
||||
{
|
||||
var dic = obj as Dictionary<string, object>;
|
||||
if (dic.ContainsKey(CsName)) dic[CsName] = val;
|
||||
else dic.Add(CsName, val);
|
||||
return;
|
||||
}
|
||||
Table.SetPropertyValue(obj, CsName, Utils.GetDataReaderValue(CsType, val));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -120,6 +120,28 @@ namespace FreeSql.Internal.Model
|
||||
/// not in (1,2,3)<para></para>
|
||||
/// 此时 Value 的值格式为逗号分割:value1,value2,value3... 或者数组
|
||||
/// </summary>
|
||||
NotAny
|
||||
NotAny,
|
||||
|
||||
/// <summary>
|
||||
/// 自定义解析,此时 Field 为反射信息,Value 为静态方法的参数(string)<para></para>
|
||||
/// 示范:{ Operator: "Custom", Field: "RawSql webapp1.DynamicFilterCustom,webapp1", Value: "(id,name) in ((1,'k'),(2,'m'))" }<para></para>
|
||||
/// 注意:使用者自己承担【注入风险】<para></para>
|
||||
/// 静态方法定义示范:<para></para>
|
||||
/// namespace webapp1<para></para>
|
||||
/// {<para></para>
|
||||
/// public class DynamicFilterCustom<para></para>
|
||||
/// {<para></para>
|
||||
/// [DynamicFilterCustom]<para></para>
|
||||
/// public static string RawSql(string value) => value;<para></para>
|
||||
/// }<para></para>
|
||||
/// }<para></para>
|
||||
/// </summary>
|
||||
Custom
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 授权 DynamicFilter 支持 Custom 自定义解析
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class DynamicFilterCustomAttribute : Attribute { }
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ namespace FreeSql.Internal.Model
|
||||
public bool DisableSyncStructure { get; set; }
|
||||
public string Comment { get; internal set; }
|
||||
public bool IsRereadSql { get; internal set; }
|
||||
public bool IsDictionaryType { get; internal set; }
|
||||
|
||||
public ColumnInfo VersionColumn { get; set; }
|
||||
|
||||
|
@ -17,6 +17,7 @@ namespace FreeSql.Internal.ObjectPool
|
||||
public bool IsThrowGetTimeoutException { get; set; } = true;
|
||||
public bool IsAutoDisposeWithSystem { get; set; } = true;
|
||||
public int CheckAvailableInterval { get; set; } = 5;
|
||||
public int Weight { get; set; } = 1;
|
||||
|
||||
public Func<T> CreateObject;
|
||||
public Action<Object<T>> OnGetObject;
|
||||
|
@ -48,6 +48,11 @@ namespace FreeSql.Internal.ObjectPool
|
||||
/// </summary>
|
||||
int CheckAvailableInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权重
|
||||
/// </summary>
|
||||
int Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对象池的对象被创建时
|
||||
/// </summary>
|
||||
|
@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
@ -118,7 +119,7 @@ namespace FreeSql.Internal
|
||||
var leftBt = colattr.DbType.IndexOf('(');
|
||||
colattr.DbType = colattr.DbType.Substring(0, leftBt).ToUpper() + colattr.DbType.Substring(leftBt);
|
||||
}
|
||||
else
|
||||
else if (common._orm.Ado.DataType != DataType.ClickHouse)
|
||||
colattr.DbType = colattr.DbType.ToUpper();
|
||||
|
||||
if (colattrIsNull == false && colattrIsNullable == true) colattr.DbType = colattr.DbType.Replace("NOT NULL", "");
|
||||
@ -129,12 +130,13 @@ namespace FreeSql.Internal
|
||||
if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower();
|
||||
if (common.CodeFirst.IsSyncStructureToUpper) colattr.Name = colattr.Name.ToUpper();
|
||||
|
||||
if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false)
|
||||
if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false && common._orm.Ado.DataType != DataType.ClickHouse)
|
||||
{
|
||||
colattr.IsNullable = false;
|
||||
colattr.DbType = Regex.Replace(colattr.DbType, @"\bNULL\b", "").Trim() + " NOT NULL";
|
||||
}
|
||||
if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", "");
|
||||
else if (colattr.IsNullable == true && !colattr.DbType.Contains("Nullable") && common._orm.Ado.DataType == DataType.ClickHouse) colattr.DbType = $"Nullable({colattr.DbType})";
|
||||
colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m =>
|
||||
{
|
||||
var tmpLt = Regex.Replace(m.Groups[0].Value, @"\s", "");
|
||||
@ -203,6 +205,36 @@ namespace FreeSql.Internal
|
||||
// else if (Math.Abs(dt.Subtract(DateTime.UtcNow).TotalSeconds) < 60)
|
||||
// col.DbDefaultValue = common.NowUtc;
|
||||
//}
|
||||
|
||||
if (common._orm.Ado.DataType == DataType.GBase)
|
||||
{
|
||||
if (colattr.IsIdentity == true)
|
||||
{
|
||||
var colType = col.CsType.NullableTypeOrThis();
|
||||
if (colType == typeof(int) || colType == typeof(uint))
|
||||
colattr.DbType = "SERIAL";
|
||||
else if (colType == typeof(long) || colType == typeof(ulong))
|
||||
colattr.DbType = "SERIAL8";
|
||||
}
|
||||
if (colattr.MapType.NullableTypeOrThis() == typeof(DateTime))
|
||||
{
|
||||
if (colattr._Precision == null)
|
||||
{
|
||||
colattr.DbType = "DATETIME YEAR TO FRACTION(3)";
|
||||
colattr.Precision = 3;
|
||||
col.DbPrecision = 3;
|
||||
}
|
||||
else if (colattr._Precision == 0)
|
||||
{
|
||||
colattr.DbType = "DATETIME YEAR TO SECOND";
|
||||
}
|
||||
else if (colattr._Precision > 0)
|
||||
{
|
||||
colattr.DbType = $"DATETIME YEAR TO FRACTION({colattr.Precision})";
|
||||
col.DbPrecision = (byte)colattr.Precision;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (colattr.ServerTime != DateTimeKind.Unspecified && new[] { typeof(DateTime), typeof(DateTimeOffset) }.Contains(colattr.MapType.NullableTypeOrThis()))
|
||||
{
|
||||
var commonNow = common.Now;
|
||||
@ -234,12 +266,13 @@ namespace FreeSql.Internal
|
||||
{
|
||||
int strlen = colattr.StringLength;
|
||||
var charPatten = @"(CHARACTER|CHAR2|CHAR)\s*(\([^\)]*\))?";
|
||||
var strNotNull = colattr.IsNullable == false ? " NOT NULL" : "";
|
||||
switch (common._orm.Ado.DataType)
|
||||
{
|
||||
case DataType.MySql:
|
||||
case DataType.OdbcMySql:
|
||||
if (strlen == -2) colattr.DbType = "LONGTEXT";
|
||||
else if (strlen < 0) colattr.DbType = "TEXT";
|
||||
if (strlen == -2) colattr.DbType = $"LONGTEXT{strNotNull}";
|
||||
else if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.SqlServer:
|
||||
@ -252,15 +285,15 @@ namespace FreeSql.Internal
|
||||
case DataType.KingbaseES:
|
||||
case DataType.OdbcKingbaseES:
|
||||
case DataType.ShenTong:
|
||||
if (strlen < 0) colattr.DbType = "TEXT";
|
||||
if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.Oracle:
|
||||
if (strlen < 0) colattr.DbType = "NCLOB"; //v1.3.2+ https://github.com/dotnetcore/FreeSql/issues/259
|
||||
if (strlen < 0) colattr.DbType = $"NCLOB{strNotNull}"; //v1.3.2+ https://github.com/dotnetcore/FreeSql/issues/259
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.Dameng:
|
||||
if (strlen < 0) colattr.DbType = "TEXT";
|
||||
if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.OdbcOracle:
|
||||
@ -269,17 +302,21 @@ namespace FreeSql.Internal
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.Sqlite:
|
||||
if (strlen < 0) colattr.DbType = "TEXT";
|
||||
if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.MsAccess:
|
||||
charPatten = @"(CHAR|CHAR2|CHARACTER|TEXT)\s*(\([^\)]*\))?";
|
||||
if (strlen < 0) colattr.DbType = "LONGTEXT";
|
||||
if (strlen < 0) colattr.DbType = $"LONGTEXT{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.Firebird:
|
||||
charPatten = @"(CHAR|CHAR2|CHARACTER|TEXT)\s*(\([^\)]*\))?";
|
||||
if (strlen < 0) colattr.DbType = "BLOB SUB_TYPE 1";
|
||||
if (strlen < 0) colattr.DbType = $"BLOB SUB_TYPE 1{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.GBase:
|
||||
if (strlen < 0) colattr.DbType = $"TEXT{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, charPatten, $"$1({strlen})");
|
||||
break;
|
||||
}
|
||||
@ -289,12 +326,13 @@ namespace FreeSql.Internal
|
||||
{
|
||||
int strlen = colattr.StringLength;
|
||||
var bytePatten = @"(VARBINARY|BINARY|BYTEA)\s*(\([^\)]*\))?";
|
||||
var strNotNull = colattr.IsNullable == false ? " NOT NULL" : "";
|
||||
switch (common._orm.Ado.DataType)
|
||||
{
|
||||
case DataType.MySql:
|
||||
case DataType.OdbcMySql:
|
||||
if (strlen == -2) colattr.DbType = "LONGBLOB";
|
||||
else if (strlen < 0) colattr.DbType = "BLOB";
|
||||
if (strlen == -2) colattr.DbType = $"LONGBLOB{strNotNull}";
|
||||
else if (strlen < 0) colattr.DbType = $"BLOB{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, bytePatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.SqlServer:
|
||||
@ -307,27 +345,30 @@ namespace FreeSql.Internal
|
||||
case DataType.KingbaseES:
|
||||
case DataType.OdbcKingbaseES:
|
||||
case DataType.ShenTong: //驱动引发的异常:“System.Data.OscarClient.OscarException”(位于 System.Data.OscarClient.dll 中)
|
||||
colattr.DbType = "BYTEA"; //变长二进制串
|
||||
colattr.DbType = $"BYTEA{strNotNull}"; //变长二进制串
|
||||
break;
|
||||
case DataType.Oracle:
|
||||
colattr.DbType = "BLOB";
|
||||
colattr.DbType = $"BLOB{strNotNull}";
|
||||
break;
|
||||
case DataType.Dameng:
|
||||
colattr.DbType = "BLOB";
|
||||
colattr.DbType = $"BLOB{strNotNull}";
|
||||
break;
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.OdbcDameng:
|
||||
colattr.DbType = "BLOB";
|
||||
colattr.DbType = $"BLOB{strNotNull}";
|
||||
break;
|
||||
case DataType.Sqlite:
|
||||
colattr.DbType = "BLOB";
|
||||
colattr.DbType = $"BLOB{strNotNull}";
|
||||
break;
|
||||
case DataType.MsAccess:
|
||||
if (strlen < 0) colattr.DbType = "BLOB";
|
||||
if (strlen < 0) colattr.DbType = $"BLOB{strNotNull}";
|
||||
else colattr.DbType = Regex.Replace(colattr.DbType, bytePatten, $"$1({strlen})");
|
||||
break;
|
||||
case DataType.Firebird:
|
||||
colattr.DbType = "BLOB";
|
||||
colattr.DbType = $"BLOB{strNotNull}";
|
||||
break;
|
||||
case DataType.GBase:
|
||||
colattr.DbType = $"BYTE{strNotNull}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1234,12 +1275,13 @@ namespace FreeSql.Internal
|
||||
});
|
||||
|
||||
public static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter)
|
||||
where T : IDataParameter
|
||||
{
|
||||
if (string.IsNullOrEmpty(sql) || obj == null) return new T[0];
|
||||
var isCheckSql = sql != "*";
|
||||
var ttype = typeof(T);
|
||||
var type = obj.GetType();
|
||||
if (type == ttype) return new[] { (T)Convert.ChangeType(obj, type) };
|
||||
if (ttype.IsAssignableFrom(type)) return new[] { (T)obj };
|
||||
var ret = new List<T>();
|
||||
var dic = obj as IDictionary;
|
||||
if (dic != null)
|
||||
@ -1250,7 +1292,7 @@ namespace FreeSql.Internal
|
||||
if (isCheckSql && string.IsNullOrEmpty(paramPrefix) == false && sql.IndexOf($"{paramPrefix}{dbkey}", StringComparison.CurrentCultureIgnoreCase) == -1) continue;
|
||||
var val = dic[key];
|
||||
var valType = val == null ? typeof(string) : val.GetType();
|
||||
if (valType == ttype) ret.Add((T)Convert.ChangeType(val, ttype));
|
||||
if (ttype.IsAssignableFrom(valType)) ret.Add((T)val);
|
||||
else ret.Add(constructorParamter(dbkey, valType, val));
|
||||
}
|
||||
}
|
||||
@ -1261,7 +1303,7 @@ namespace FreeSql.Internal
|
||||
{
|
||||
if (isCheckSql && string.IsNullOrEmpty(paramPrefix) == false && sql.IndexOf($"{paramPrefix}{p.Name}", StringComparison.CurrentCultureIgnoreCase) == -1) continue;
|
||||
var pvalue = p.GetValue(obj, null);
|
||||
if (p.PropertyType == ttype) ret.Add((T)Convert.ChangeType(pvalue, ttype));
|
||||
if (ttype.IsAssignableFrom(p.PropertyType)) ret.Add((T)pvalue);
|
||||
else ret.Add(constructorParamter(p.Name, p.PropertyType, pvalue));
|
||||
}
|
||||
}
|
||||
@ -1333,7 +1375,7 @@ namespace FreeSql.Internal
|
||||
this.Value = value;
|
||||
this.DataIndex = dataIndex;
|
||||
}
|
||||
public static ConstructorInfo Constructor = typeof(RowInfo). GetConstructor(new[] { typeof(object), typeof(int) });
|
||||
public static ConstructorInfo Constructor = typeof(RowInfo).GetConstructor(new[] { typeof(object), typeof(int) });
|
||||
public static PropertyInfo PropertyValue = typeof(RowInfo).GetProperty("Value");
|
||||
public static PropertyInfo PropertyDataIndex = typeof(RowInfo).GetProperty("DataIndex");
|
||||
}
|
||||
@ -1351,6 +1393,7 @@ namespace FreeSql.Internal
|
||||
switch (orm.Ado.DataType)
|
||||
{
|
||||
case DataType.Dameng: //OdbcDameng 不会报错
|
||||
case DataType.GBase:
|
||||
if (dr.IsDBNull(index)) return null;
|
||||
break;
|
||||
}
|
||||
@ -1464,7 +1507,7 @@ namespace FreeSql.Internal
|
||||
), new[] { typeExp, indexesExp, rowExp, dataIndexExp, commonUtilExp }).Compile();
|
||||
}
|
||||
|
||||
if (type == typeof(object) && indexes != null)
|
||||
if (type == typeof(object) && indexes != null || type == typeof(Dictionary<string, object>))
|
||||
{
|
||||
Func<Type, int[], DbDataReader, int, CommonUtils, RowInfo> dynamicFunc = (type2, indexes2, row2, dataindex2, commonUtils2) =>
|
||||
{
|
||||
@ -1812,7 +1855,7 @@ namespace FreeSql.Internal
|
||||
static MethodInfo MethodBigIntegerParse = typeof(Utils).GetMethod("ToBigInteger", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null);
|
||||
static PropertyInfo PropertyDateTimeOffsetDateTime = typeof(DateTimeOffset).GetProperty("DateTime", BindingFlags.Instance | BindingFlags.Public);
|
||||
static PropertyInfo PropertyDateTimeTicks = typeof(DateTime).GetProperty("Ticks", BindingFlags.Instance | BindingFlags.Public);
|
||||
static ConstructorInfo CtorDateTimeOffsetArgsTicks = typeof(DateTimeOffset). GetConstructor(new[] { typeof(long), typeof(TimeSpan) });
|
||||
static ConstructorInfo CtorDateTimeOffsetArgsTicks = typeof(DateTimeOffset).GetConstructor(new[] { typeof(long), typeof(TimeSpan) });
|
||||
static Encoding DefaultEncoding = Encoding.UTF8;
|
||||
static MethodInfo MethodEncodingGetBytes = typeof(Encoding).GetMethod("GetBytes", new[] { typeof(string) });
|
||||
static MethodInfo MethodEncodingGetString = typeof(Encoding).GetMethod("GetString", new[] { typeof(byte[]) });
|
||||
@ -1831,7 +1874,7 @@ namespace FreeSql.Internal
|
||||
{
|
||||
if (type.IsArray)
|
||||
{
|
||||
switch (type.FullName)
|
||||
switch (type.FullName)
|
||||
{
|
||||
case "System.Byte[]":
|
||||
return Expression.IfThenElse(
|
||||
|
Reference in New Issue
Block a user