Update Core

This commit is contained in:
sunkaixuna
2021-11-20 00:31:38 +08:00
parent 8ae679116c
commit 3c706401c9
15 changed files with 332 additions and 148 deletions

View File

@@ -43,7 +43,7 @@ namespace SqlSugar
{ {
this.Context.Ado.BeginTran(); this.Context.Ado.BeginTran();
var result = await _ExecuteCommandAsync(); var result = await _ExecuteCommandAsync();
this.Context.Ado.BeginTran(); this.Context.Ado.CommitTran();
return result; return result;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -152,6 +152,7 @@ namespace SqlSugar
column.EntityName = result.EntityName; column.EntityName = result.EntityName;
column.PropertyName = property.Name; column.PropertyName = property.Name;
column.PropertyInfo = property; column.PropertyInfo = property;
column.UnderType = UtilMethods.GetUnderType(column.PropertyInfo.PropertyType);
if (sugarColumn.IsNullOrEmpty()) if (sugarColumn.IsNullOrEmpty())
{ {
column.DbColumnName = property.Name; column.DbColumnName = property.Name;

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SqlSugar
{
public class FastBuilder
{
public SqlSugarProvider Context { get; set; }
public virtual string UpdateSql { get; set; } = @"UPDATE TM
SET {0}
FROM {1} TM
INNER JOIN {2} TE ON {3} ";
public virtual void CloseDb()
{
if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection && this.Context.Ado.Transaction == null)
{
this.Context.Ado.Connection.Close();
}
}
public virtual async Task<int> UpdateByTempAsync(string tableName, string tempName, string[] updateColumns, string[] whereColumns)
{
Check.ArgumentNullException(!updateColumns.Any(), "update columns count is 0");
Check.ArgumentNullException(!whereColumns.Any(), "where columns count is 0");
var sets = string.Join(",", updateColumns.Select(it => $"TM.{it}=TE.{it}"));
var wheres = string.Join(",", whereColumns.Select(it => $"TM.{it}=TE.{it}"));
string sql = string.Format(UpdateSql, sets, tableName, tempName, wheres);
return await this.Context.Ado.ExecuteCommandAsync(sql);
}
public virtual async Task CreateTempAsync<T>(DataTable dt) where T : class, new()
{
await this.Context.UnionAll(
this.Context.Queryable<T>().Where(it => false).AS(dt.TableName),
this.Context.Queryable<T>().Where(it => false).AS(dt.TableName)).Select("top 1 * into #temp").ToListAsync();
dt.TableName = "#temp";
}
}
}

View File

@@ -6,11 +6,10 @@ using System.Threading.Tasks;
using System.Linq; using System.Linq;
namespace SqlSugar namespace SqlSugar
{ {
public class FastestProvider<T>:IFastest<T> where T:class,new() public partial class FastestProvider<T>:IFastest<T> where T:class,new()
{ {
private SqlSugarProvider context; private SqlSugarProvider context;
private ISugarQueryable<T> queryable; private ISugarQueryable<T> queryable;
private string AsName { get; set; }
private EntityInfo entityInfo { get; set; } private EntityInfo entityInfo { get; set; }
public FastestProvider(SqlSugarProvider sqlSugarProvider) public FastestProvider(SqlSugarProvider sqlSugarProvider)
{ {
@@ -18,19 +17,31 @@ namespace SqlSugar
this.queryable = this.context.Queryable<T>(); this.queryable = this.context.Queryable<T>();
entityInfo=this.context.EntityMaintenance.GetEntityInfo<T>(); entityInfo=this.context.EntityMaintenance.GetEntityInfo<T>();
} }
#region Api
#region BulkCopy
public int BulkCopy(List<T> datas) public int BulkCopy(List<T> datas)
{ {
return BulkCopyAsync(datas).ConfigureAwait(true).GetAwaiter().GetResult(); return BulkCopyAsync(datas).ConfigureAwait(true).GetAwaiter().GetResult();
} }
public async Task<int> BulkCopyAsync(List<T> datas) public async Task<int> BulkCopyAsync(List<T> datas)
{ {
DataTable dt = ToDdateTable(datas); if (Size > 0)
IFastBuilder buider = new SqlServerFastBuilder(); {
buider.Context = context; int resul=0;
var result = await buider.ExecuteBulkCopyAsync(dt); await this.context.Utilities.PageEachAsync(datas, Size, async item =>
return result; {
resul+= await _BulkCopy(item);
});
return resul;
}
else
{
return await _BulkCopy(datas);
}
} }
#endregion
#region BulkUpdate
public int BulkUpdate(List<T> datas) public int BulkUpdate(List<T> datas)
{ {
return BulkUpdateAsync(datas).ConfigureAwait(true).GetAwaiter().GetResult(); return BulkUpdateAsync(datas).ConfigureAwait(true).GetAwaiter().GetResult();
@@ -41,7 +52,31 @@ namespace SqlSugar
var updateColumns = entityInfo.Columns.Where(it => !it.IsPrimarykey&&!it.IsIdentity&&!it.IsOnlyIgnoreUpdate&&!it.IsIgnore).Select(it => it.DbColumnName ?? it.PropertyName).ToArray(); var updateColumns = entityInfo.Columns.Where(it => !it.IsPrimarykey&&!it.IsIdentity&&!it.IsOnlyIgnoreUpdate&&!it.IsIgnore).Select(it => it.DbColumnName ?? it.PropertyName).ToArray();
return await BulkUpdateAsync(datas,whereColumns,updateColumns); return await BulkUpdateAsync(datas,whereColumns,updateColumns);
} }
public int BulkUpdate(List<T> datas, string[] whereColumns, string[] updateColumns)
{
return BulkUpdateAsync(datas,whereColumns,updateColumns).ConfigureAwait(true).GetAwaiter().GetResult();
}
public async Task<int> BulkUpdateAsync(List<T> datas,string [] whereColumns,string [] updateColumns) public async Task<int> BulkUpdateAsync(List<T> datas,string [] whereColumns,string [] updateColumns)
{
if (Size > 0)
{
int resul = 0;
await this.context.Utilities.PageEachAsync(datas, Size, async item =>
{
resul += await _BulkUpdate(item, whereColumns, updateColumns);
});
return resul;
}
else
{
return await _BulkUpdate(datas, whereColumns, updateColumns);
}
}
#endregion
#region Core
private async Task<int> _BulkUpdate(List<T> datas, string[] whereColumns, string[] updateColumns)
{ {
var isAuto = this.context.CurrentConnectionConfig.IsAutoCloseConnection; var isAuto = this.context.CurrentConnectionConfig.IsAutoCloseConnection;
this.context.CurrentConnectionConfig.IsAutoCloseConnection = false; this.context.CurrentConnectionConfig.IsAutoCloseConnection = false;
@@ -56,107 +91,15 @@ namespace SqlSugar
this.context.CurrentConnectionConfig.IsAutoCloseConnection = isAuto; this.context.CurrentConnectionConfig.IsAutoCloseConnection = isAuto;
return result; return result;
} }
#endregion private async Task<int> _BulkCopy(List<T> datas)
#region Setting
public IFastest<T> AS(string tableName)
{ {
this.AsName = tableName; DataTable dt = ToDdateTable(datas);
return this; IFastBuilder buider =GetBuider();
buider.Context = context;
var result = await buider.ExecuteBulkCopyAsync(dt);
return result;
} }
#endregion #endregion
#region Helper
private SqlServerFastBuilder GetBuider()
{
switch (this.context.CurrentConnectionConfig.DbType)
{
case DbType.MySql:
break;
case DbType.SqlServer:
return new SqlServerFastBuilder();
case DbType.Sqlite:
break;
case DbType.Oracle:
break;
case DbType.PostgreSQL:
break;
case DbType.Dm:
break;
case DbType.Kdbndp:
break;
case DbType.Oscar:
break;
default:
break;
}
throw new Exception(this.context.CurrentConnectionConfig.DbType + "开发中");
}
private DataTable ToDdateTable(List<T> datas)
{
DataTable tempDataTable = ReflectionInoCore<DataTable>.GetInstance().GetOrCreate("BulkCopyAsync" + typeof(T).FullName,
() =>
{
if (AsName == null)
{
return queryable.Where(it => false).ToDataTable();
}
else
{
return queryable.AS(AsName).Where(it => false).ToDataTable();
}
}
);
var dt = new DataTable();
foreach (DataColumn item in tempDataTable.Columns)
{
dt.Columns.Add(item.ColumnName, item.DataType);
}
dt.TableName = GetTableName();
var columns = entityInfo.Columns;
foreach (var item in datas)
{
var dr = dt.NewRow();
foreach (var column in columns)
{
if (column.IsIgnore || column.IsOnlyIgnoreInsert)
{
continue;
}
var name = column.DbColumnName;
if (name == null)
{
name = column.PropertyName;
}
var value = ValueConverter(column, PropertyCallAdapterProvider<T>.GetInstance(column.PropertyName).InvokeGet(item));
dr[name] = value;
}
dt.Rows.Add(dr);
}
return dt;
}
private string GetTableName()
{
if (this.AsName.HasValue())
{
return queryable.SqlBuilder.GetTranslationTableName(AsName);
}
else
{
return queryable.SqlBuilder.GetTranslationTableName(entityInfo.DbTableName);
}
}
private object ValueConverter(EntityColumnInfo columnInfo, object value)
{
if (value == null)
return value;
if (value is DateTime && (DateTime)value == DateTime.MinValue)
{
value = Convert.ToDateTime("1900-01-01");
}
return value;
}
#endregion
} }
} }

View File

@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SqlSugar
{
public partial class FastestProvider<T> : IFastest<T> where T : class, new()
{
private IFastBuilder GetBuider()
{
switch (this.context.CurrentConnectionConfig.DbType)
{
case DbType.MySql:
return new MySqlFastBuilder();
case DbType.SqlServer:
return new SqlServerFastBuilder();
case DbType.Sqlite:
break;
case DbType.Oracle:
break;
case DbType.PostgreSQL:
break;
case DbType.Dm:
break;
case DbType.Kdbndp:
break;
case DbType.Oscar:
break;
default:
break;
}
throw new Exception(this.context.CurrentConnectionConfig.DbType + "开发中");
}
private DataTable ToDdateTable(List<T> datas)
{
DataTable tempDataTable = ReflectionInoCore<DataTable>.GetInstance().GetOrCreate("BulkCopyAsync" + typeof(T).FullName,
() =>
{
if (AsName == null)
{
return queryable.Where(it => false).ToDataTable();
}
else
{
return queryable.AS(AsName).Where(it => false).ToDataTable();
}
}
);
var dt = new DataTable();
foreach (DataColumn item in tempDataTable.Columns)
{
dt.Columns.Add(item.ColumnName, item.DataType);
}
dt.TableName = GetTableName();
var columns = entityInfo.Columns;
foreach (var item in datas)
{
var dr = dt.NewRow();
foreach (var column in columns)
{
if (column.IsIgnore || column.IsOnlyIgnoreInsert)
{
continue;
}
var name = column.DbColumnName;
if (name == null)
{
name = column.PropertyName;
}
var value = ValueConverter(column, PropertyCallAdapterProvider<T>.GetInstance(column.PropertyName).InvokeGet(item));
dr[name] = value;
}
dt.Rows.Add(dr);
}
return dt;
}
private string GetTableName()
{
if (this.AsName.HasValue())
{
return queryable.SqlBuilder.GetTranslationTableName(AsName);
}
else
{
return queryable.SqlBuilder.GetTranslationTableName(entityInfo.DbTableName);
}
}
private object ValueConverter(EntityColumnInfo columnInfo, object value)
{
if (value == null)
return value;
if (value is DateTime && (DateTime)value == DateTime.MinValue)
{
value = Convert.ToDateTime("1900-01-01");
}
else if (columnInfo.IsJson)
{
columnInfo.IsJson = true;
}
else if (columnInfo.IsArray)
{
columnInfo.IsArray = true;
}
else if (columnInfo.UnderType.IsEnum() )
{
value = Convert.ToInt64(value);
}
else if (columnInfo.IsJson && value != null)
{
value = this.context.Utilities.SerializeObject(value);
}
else if (columnInfo.IsTranscoding && value.HasValue())
{
value = UtilMethods.EncodeBase64(value.ToString());
}
return value;
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SqlSugar
{
public partial class FastestProvider<T> : IFastest<T> where T : class, new()
{
private string AsName { get; set; }
private int Size { get; set; }
public IFastest<T> AS(string tableName)
{
this.AsName = tableName;
return this;
}
public IFastest<T> PageSize(int size)
{
this.Size = size;
return this;
}
}
}

View File

@@ -44,7 +44,7 @@ namespace SqlSugar
{ {
this.Context.Ado.BeginTran(); this.Context.Ado.BeginTran();
var result = await _ExecuteCommandAsync(); var result = await _ExecuteCommandAsync();
this.Context.Ado.BeginTran(); this.Context.Ado.CommitTran();
return result; return result;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -35,5 +35,6 @@ namespace SqlSugar
public string[] IndexGroupNameList { get; set; } public string[] IndexGroupNameList { get; set; }
public string[] UIndexGroupNameList { get; set; } public string[] UIndexGroupNameList { get; set; }
public bool IsArray { get; set; } public bool IsArray { get; set; }
public Type UnderType { get; set; }
} }
} }

View File

@@ -6,11 +6,11 @@ using System.Threading.Tasks;
namespace SqlSugar namespace SqlSugar
{ {
public class SqlSguarTransaction:IDisposable public class SqlSugarTransaction:IDisposable
{ {
private readonly SqlSugarClient context; private readonly SqlSugarClient context;
public SqlSguarTransaction(SqlSugarClient client) public SqlSugarTransaction(SqlSugarClient client)
{ {
context = client; context = client;
context.BeginTran(); context.BeginTran();

View File

@@ -8,9 +8,13 @@ namespace SqlSugar
public interface IFastest<T> public interface IFastest<T>
{ {
IFastest<T> AS(string tableName); IFastest<T> AS(string tableName);
int BulkCopy(List<T> datas); int BulkCopy(List<T> datas);
Task<int> BulkCopyAsync(List<T> datas); Task<int> BulkCopyAsync(List<T> datas);
int BulkUpdate(List<T> datas); int BulkUpdate(List<T> datas);
Task<int> BulkUpdateAsync(List<T> datas); Task<int> BulkUpdateAsync(List<T> datas);
int BulkUpdate(List<T> datas, string[] whereColumns, string[] updateColumns);
Task<int> BulkUpdateAsync(List<T> datas, string[] whereColumns, string[] updateColumns);
} }
} }

View File

@@ -13,7 +13,7 @@ namespace SqlSugar
void RollbackTran(); void RollbackTran();
void ChangeDatabase(dynamic configId); void ChangeDatabase(dynamic configId);
void ChangeDatabase(Func<ConnectionConfig, bool> changeExpression); void ChangeDatabase(Func<ConnectionConfig, bool> changeExpression);
SqlSguarTransaction UseTran(); SqlSugarTransaction UseTran();
DbResult<bool> UseTran(Action action, Action<Exception> errorCallBack = null); DbResult<bool> UseTran(Action action, Action<Exception> errorCallBack = null);
Task<DbResult<bool>> UseTranAsync(Func<Task> action, Action<Exception> errorCallBack = null); Task<DbResult<bool>> UseTranAsync(Func<Task> action, Action<Exception> errorCallBack = null);
DbResult<T> UseTran<T>(Func<T> action, Action<Exception> errorCallBack = null); DbResult<T> UseTran<T>(Func<T> action, Action<Exception> errorCallBack = null);

View File

@@ -0,0 +1,72 @@
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SqlSugar
{
public class MySqlFastBuilder:FastBuilder,IFastBuilder
{
public override string UpdateSql { get; set; } = @"UPDATE {1} TM INNER JOIN {2} TE ON {3} SET {0} ";
public async Task<int> ExecuteBulkCopyAsync(DataTable dt)
{
var dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "failFiles");
DirectoryInfo dir = new DirectoryInfo(dllPath);
if (!dir.Exists)
{
dir.Create();
}
var fileName = Path.Combine(dllPath, Guid.NewGuid().ToString() + ".csv");
var dataTableToCsv =new MySqlBlukCopy<object>(this.Context.Context,null,null).DataTableToCsvString(dt);
File.WriteAllText(fileName, dataTableToCsv, new UTF8Encoding(false));
MySqlConnection conn = this.Context.Ado.Connection as MySqlConnection;
int result = 0;
try
{
this.Context.Ado.Open();
// IsolationLevel.Parse
MySqlBulkLoader bulk = new MySqlBulkLoader(conn)
{
CharacterSet = "UTF8",
FieldTerminator = ",",
FieldQuotationCharacter = '"',
EscapeCharacter = '"',
LineTerminator = "\r\n",
FileName = fileName,
NumberOfLinesToSkip = 0,
TableName = dt.TableName,
Local = true,
};
bulk.Columns.AddRange(dt.Columns.Cast<DataColumn>().Select(colum => colum.ColumnName).Distinct().ToArray());
result= await bulk.LoadAsync();
//执行成功才删除文件
if (File.Exists(fileName))
{
File.Delete(fileName);
}
}
catch (MySqlException ex)
{
throw ex;
}
finally
{
CloseDb();
}
return result;
}
public override async Task CreateTempAsync<T>(DataTable dt)
{
dt.TableName = "temp"+SnowFlakeSingle.instance.getID();
var sql = this.Context.Queryable<T>().Where(it => false).ToSql().Key;
await this.Context.Ado.ExecuteCommandAsync($"Create TEMPORARY table {dt.TableName}({sql}) ");
}
}
}

View File

@@ -9,16 +9,9 @@ using System.Threading.Tasks;
namespace SqlSugar namespace SqlSugar
{ {
public class SqlServerFastBuilder: IFastBuilder
public class SqlServerFastBuilder:FastBuilder,IFastBuilder
{ {
public SqlSugarProvider Context { get; set; }
public string UpdateSql { get; set; } = @"UPDATE TM
SET {0}
FROM {1} TM
INNER JOIN {2} TE ON {3} ";
public async Task<int> ExecuteBulkCopyAsync(DataTable dt) public async Task<int> ExecuteBulkCopyAsync(DataTable dt)
{ {
@@ -53,30 +46,6 @@ namespace SqlSugar
} }
return copy; return copy;
} }
public void CloseDb()
{
if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection && this.Context.Ado.Transaction == null)
{
this.Context.Ado.Connection.Close();
}
}
public async Task<int> UpdateByTempAsync(string tableName, string tempName, string[] updateColumns, string[] whereColumns)
{
Check.ArgumentNullException(!updateColumns.Any(),"update columns count is 0");
Check.ArgumentNullException(!whereColumns.Any(), "where columns count is 0");
var sets = string.Join(",", updateColumns.Select(it=>$"TM.{it}=TE.{it}"));
var wheres = string.Join(",", whereColumns.Select(it => $"TM.{it}=TE.{it}"));
string sql = string.Format(UpdateSql,sets, tableName,tempName, wheres);
return await this.Context.Ado.ExecuteCommandAsync(sql);
}
public async Task CreateTempAsync<T>(DataTable dt) where T :class,new()
{
await this.Context.UnionAll(
this.Context.Queryable<T>().Where(it => false).AS(dt.TableName),
this.Context.Queryable<T>().Where(it => false).AS(dt.TableName)).Select("top 1 * into #temp").ToListAsync();
dt.TableName = "#temp";
}
} }
} }

View File

@@ -565,7 +565,7 @@ namespace SqlSugar
#endregion #endregion
#region #region Fastest
public IFastest<T> Fastest<T>() where T : class, new() public IFastest<T> Fastest<T>() where T : class, new()
{ {
return this.Context.Fastest<T>(); return this.Context.Fastest<T>();
@@ -588,9 +588,9 @@ namespace SqlSugar
var tenant= this as ITenant; var tenant= this as ITenant;
return tenant; return tenant;
} }
public SqlSguarTransaction UseTran() public SqlSugarTransaction UseTran()
{ {
return new SqlSguarTransaction(this); return new SqlSugarTransaction(this);
} }
public void AddConnection(ConnectionConfig connection) public void AddConnection(ConnectionConfig connection)
{ {

View File

@@ -612,7 +612,7 @@ namespace SqlSugar
{ {
return ScopedContext.SplitHelper(dataList); return ScopedContext.SplitHelper(dataList);
} }
public SqlSguarTransaction UseTran() public SqlSugarTransaction UseTran()
{ {
return ScopedContext.UseTran(); return ScopedContext.UseTran();
} }