mirror of
https://gitee.com/dotnetchina/SqlSugar.git
synced 2025-07-15 14:04:44 +08:00
Synchronization code
This commit is contained in:
parent
0d8f3e169e
commit
392dce7af6
@ -39,6 +39,8 @@ namespace SqlSugar
|
|||||||
internal bool OldClearParameters { get; set; }
|
internal bool OldClearParameters { get; set; }
|
||||||
public IDataParameterCollection DataReaderParameters { get; set; }
|
public IDataParameterCollection DataReaderParameters { get; set; }
|
||||||
public TimeSpan SqlExecutionTime { get { return AfterTime - BeforeTime; } }
|
public TimeSpan SqlExecutionTime { get { return AfterTime - BeforeTime; } }
|
||||||
|
public TimeSpan ConnectionExecutionTime { get { return CheckConnectionAfterTime - CheckConnectionBeforeTime; } }
|
||||||
|
public TimeSpan GetDataExecutionTime { get { return GetDataAfterTime - GetDataBeforeTime; } }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add, delete and modify: the number of affected items;
|
/// Add, delete and modify: the number of affected items;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -47,6 +49,10 @@ namespace SqlSugar
|
|||||||
public bool IsDisableMasterSlaveSeparation { get; set; }
|
public bool IsDisableMasterSlaveSeparation { get; set; }
|
||||||
internal DateTime BeforeTime = DateTime.MinValue;
|
internal DateTime BeforeTime = DateTime.MinValue;
|
||||||
internal DateTime AfterTime = DateTime.MinValue;
|
internal DateTime AfterTime = DateTime.MinValue;
|
||||||
|
internal DateTime GetDataBeforeTime = DateTime.MinValue;
|
||||||
|
internal DateTime GetDataAfterTime = DateTime.MinValue;
|
||||||
|
internal DateTime CheckConnectionBeforeTime = DateTime.MinValue;
|
||||||
|
internal DateTime CheckConnectionAfterTime = DateTime.MinValue;
|
||||||
public virtual IDbBind DbBind
|
public virtual IDbBind DbBind
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -66,6 +72,10 @@ namespace SqlSugar
|
|||||||
public virtual bool IsClearParameters { get; set; }
|
public virtual bool IsClearParameters { get; set; }
|
||||||
public virtual Action<string, SugarParameter[]> LogEventStarting => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuting;
|
public virtual Action<string, SugarParameter[]> LogEventStarting => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuting;
|
||||||
public virtual Action<string, SugarParameter[]> LogEventCompleted => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuted;
|
public virtual Action<string, SugarParameter[]> LogEventCompleted => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuted;
|
||||||
|
public virtual Action<IDbConnection> CheckConnectionExecuting => this.Context.CurrentConnectionConfig.AopEvents?.CheckConnectionExecuting;
|
||||||
|
public virtual Action<IDbConnection, TimeSpan> CheckConnectionExecuted => this.Context.CurrentConnectionConfig.AopEvents?.CheckConnectionExecuted;
|
||||||
|
public virtual Action<string, SugarParameter[]> OnGetDataReadering => this.Context.CurrentConnectionConfig.AopEvents?.OnGetDataReadering;
|
||||||
|
public virtual Action<string, SugarParameter[], TimeSpan> OnGetDataReadered => this.Context.CurrentConnectionConfig.AopEvents?.OnGetDataReadered;
|
||||||
public virtual Func<string, SugarParameter[], KeyValuePair<string, SugarParameter[]>> ProcessingEventStartingSQL => this.Context.CurrentConnectionConfig.AopEvents?.OnExecutingChangeSql;
|
public virtual Func<string, SugarParameter[], KeyValuePair<string, SugarParameter[]>> ProcessingEventStartingSQL => this.Context.CurrentConnectionConfig.AopEvents?.OnExecutingChangeSql;
|
||||||
protected virtual Func<string, string> FormatSql { get; set; }
|
protected virtual Func<string, string> FormatSql { get; set; }
|
||||||
public virtual Action<SqlSugarException> ErrorEvent => this.Context.CurrentConnectionConfig.AopEvents?.OnError;
|
public virtual Action<SqlSugarException> ErrorEvent => this.Context.CurrentConnectionConfig.AopEvents?.OnError;
|
||||||
@ -175,6 +185,7 @@ namespace SqlSugar
|
|||||||
}
|
}
|
||||||
public virtual void CheckConnection()
|
public virtual void CheckConnection()
|
||||||
{
|
{
|
||||||
|
this.CheckConnectionBefore(this.Connection);
|
||||||
if (this.Connection.State != ConnectionState.Open)
|
if (this.Connection.State != ConnectionState.Open)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -190,10 +201,12 @@ namespace SqlSugar
|
|||||||
Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message+$"DbType=\"{this.Context.CurrentConnectionConfig.DbType}\";ConfigId=\"{this.Context.CurrentConnectionConfig.ConfigId}\"");
|
Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message+$"DbType=\"{this.Context.CurrentConnectionConfig.DbType}\";ConfigId=\"{this.Context.CurrentConnectionConfig.ConfigId}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.CheckConnectionAfter(this.Connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task CheckConnectionAsync()
|
public virtual async Task CheckConnectionAsync()
|
||||||
{
|
{
|
||||||
|
this.CheckConnectionBefore(this.Connection);
|
||||||
if (this.Connection.State != ConnectionState.Open)
|
if (this.Connection.State != ConnectionState.Open)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -205,6 +218,31 @@ namespace SqlSugar
|
|||||||
Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message + $"DbType=\"{this.Context.CurrentConnectionConfig.DbType}\";ConfigId=\"{this.Context.CurrentConnectionConfig.ConfigId}\"");
|
Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message + $"DbType=\"{this.Context.CurrentConnectionConfig.DbType}\";ConfigId=\"{this.Context.CurrentConnectionConfig.ConfigId}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.CheckConnectionAfter(this.Connection);
|
||||||
|
}
|
||||||
|
public virtual void CheckConnectionBefore(IDbConnection Connection)
|
||||||
|
{
|
||||||
|
this.CheckConnectionBeforeTime = DateTime.Now;
|
||||||
|
if (this.IsEnableLogEvent)
|
||||||
|
{
|
||||||
|
Action<IDbConnection> action = CheckConnectionExecuting;
|
||||||
|
if (action != null)
|
||||||
|
{
|
||||||
|
action(Connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public virtual void CheckConnectionAfter(IDbConnection Connection)
|
||||||
|
{
|
||||||
|
this.CheckConnectionAfterTime = DateTime.Now;
|
||||||
|
if (this.IsEnableLogEvent)
|
||||||
|
{
|
||||||
|
Action<IDbConnection, TimeSpan> action = CheckConnectionExecuted;
|
||||||
|
if (action != null)
|
||||||
|
{
|
||||||
|
action(Connection,this.ConnectionExecutionTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -1015,7 +1053,10 @@ namespace SqlSugar
|
|||||||
builder.SqlQueryBuilder.sql.Append(sql);
|
builder.SqlQueryBuilder.sql.Append(sql);
|
||||||
if (parsmeterArray != null && parsmeterArray.Any())
|
if (parsmeterArray != null && parsmeterArray.Any())
|
||||||
builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray);
|
builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray);
|
||||||
using (var dataReader = this.GetDataReader(builder.SqlQueryBuilder.ToSqlString(), builder.SqlQueryBuilder.Parameters.ToArray()))
|
string sqlString = builder.SqlQueryBuilder.ToSqlString();
|
||||||
|
SugarParameter[] Parameters = builder.SqlQueryBuilder.Parameters.ToArray();
|
||||||
|
this.GetDataBefore(sqlString, Parameters);
|
||||||
|
using (var dataReader = this.GetDataReader(sqlString, Parameters))
|
||||||
{
|
{
|
||||||
DbDataReader DbReader = (DbDataReader)dataReader;
|
DbDataReader DbReader = (DbDataReader)dataReader;
|
||||||
List<T> result = new List<T>();
|
List<T> result = new List<T>();
|
||||||
@ -1076,6 +1117,7 @@ namespace SqlSugar
|
|||||||
}
|
}
|
||||||
this.Context.Ado.DataReaderParameters = null;
|
this.Context.Ado.DataReaderParameters = null;
|
||||||
}
|
}
|
||||||
|
this.GetDataAfter(sqlString, Parameters);
|
||||||
return Tuple.Create<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>, List<T7>>(result, result2, result3, result4, result5, result6, result7);
|
return Tuple.Create<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>, List<T7>>(result, result2, result3, result4, result5, result6, result7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1140,7 +1182,10 @@ namespace SqlSugar
|
|||||||
builder.SqlQueryBuilder.sql.Append(sql);
|
builder.SqlQueryBuilder.sql.Append(sql);
|
||||||
if (parsmeterArray != null && parsmeterArray.Any())
|
if (parsmeterArray != null && parsmeterArray.Any())
|
||||||
builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray);
|
builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray);
|
||||||
using (var dataReader = await this.GetDataReaderAsync(builder.SqlQueryBuilder.ToSqlString(), builder.SqlQueryBuilder.Parameters.ToArray()))
|
string sqlString = builder.SqlQueryBuilder.ToSqlString();
|
||||||
|
SugarParameter[] Parameters = builder.SqlQueryBuilder.Parameters.ToArray();
|
||||||
|
this.GetDataBefore(sqlString, Parameters);
|
||||||
|
using (var dataReader = await this.GetDataReaderAsync(sqlString, Parameters))
|
||||||
{
|
{
|
||||||
DbDataReader DbReader = (DbDataReader)dataReader;
|
DbDataReader DbReader = (DbDataReader)dataReader;
|
||||||
List<T> result = new List<T>();
|
List<T> result = new List<T>();
|
||||||
@ -1197,6 +1242,7 @@ namespace SqlSugar
|
|||||||
}
|
}
|
||||||
this.Context.Ado.DataReaderParameters = null;
|
this.Context.Ado.DataReaderParameters = null;
|
||||||
}
|
}
|
||||||
|
this.GetDataAfter(sqlString, Parameters);
|
||||||
return Tuple.Create<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>, List<T7>>(result, result2, result3, result4, result5, result6, result7);
|
return Tuple.Create<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>, List<T7>>(result, result2, result3, result4, result5, result6, result7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1551,6 +1597,44 @@ namespace SqlSugar
|
|||||||
this.OldClearParameters = false;
|
this.OldClearParameters = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public virtual void GetDataBefore(string sql, SugarParameter[] parameters)
|
||||||
|
{
|
||||||
|
this.GetDataBeforeTime = DateTime.Now;
|
||||||
|
if (this.IsEnableLogEvent)
|
||||||
|
{
|
||||||
|
Action<string, SugarParameter[]> action = OnGetDataReadering;
|
||||||
|
if (action != null)
|
||||||
|
{
|
||||||
|
if (parameters == null || parameters.Length == 0)
|
||||||
|
{
|
||||||
|
action(sql, new SugarParameter[] { });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
action(sql, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public virtual void GetDataAfter(string sql, SugarParameter[] parameters)
|
||||||
|
{
|
||||||
|
this.GetDataAfterTime = DateTime.Now;
|
||||||
|
if (this.IsEnableLogEvent)
|
||||||
|
{
|
||||||
|
Action<string, SugarParameter[], TimeSpan> action = OnGetDataReadered;
|
||||||
|
if (action != null)
|
||||||
|
{
|
||||||
|
if (parameters == null || parameters.Length == 0)
|
||||||
|
{
|
||||||
|
action(sql, new SugarParameter[] { }, GetDataExecutionTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
action(sql, parameters, GetDataExecutionTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
public virtual SugarParameter[] GetParameters(object parameters, PropertyInfo[] propertyInfo = null)
|
public virtual SugarParameter[] GetParameters(object parameters, PropertyInfo[] propertyInfo = null)
|
||||||
{
|
{
|
||||||
if (parameters == null) return null;
|
if (parameters == null) return null;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@ -22,5 +23,9 @@ namespace SqlSugar
|
|||||||
public virtual Action<object, DataFilterModel> DataExecuting { set { this.Context.CurrentConnectionConfig.AopEvents.DataExecuting = value; } }
|
public virtual Action<object, DataFilterModel> DataExecuting { set { this.Context.CurrentConnectionConfig.AopEvents.DataExecuting = value; } }
|
||||||
public Action<object, DataFilterModel> DataChangesExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.DataChangesExecuted = value; } }
|
public Action<object, DataFilterModel> DataChangesExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.DataChangesExecuted = value; } }
|
||||||
public virtual Action<object, DataAfterModel> DataExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.DataExecuted = value; } }
|
public virtual Action<object, DataAfterModel> DataExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.DataExecuted = value; } }
|
||||||
|
public Action<IDbConnection> CheckConnectionExecuting { set { this.Context.CurrentConnectionConfig.AopEvents.CheckConnectionExecuting = value; } }
|
||||||
|
public Action<IDbConnection, TimeSpan> CheckConnectionExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.CheckConnectionExecuted = value; } }
|
||||||
|
public Action<string, SugarParameter[]> OnGetDataReadering { set { this.Context.CurrentConnectionConfig.AopEvents.OnGetDataReadering = value; } }
|
||||||
|
public Action<string, SugarParameter[], TimeSpan> OnGetDataReadered { set { this.Context.CurrentConnectionConfig.AopEvents.OnGetDataReadered = value; } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,7 @@ namespace SqlSugar
|
|||||||
{
|
{
|
||||||
if (dataAfterFunc != null)
|
if (dataAfterFunc != null)
|
||||||
{
|
{
|
||||||
|
((AdoProvider)context.Ado).AfterTime = DateTime.Now;
|
||||||
var entity = context.EntityMaintenance.GetEntityInfo<T>();
|
var entity = context.EntityMaintenance.GetEntityInfo<T>();
|
||||||
foreach (var item in result)
|
foreach (var item in result)
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,10 @@ namespace SqlSugar
|
|||||||
public EntityInfo EntityInfo { get { return this.Context.EntityMaintenance.GetEntityInfo<T>(); } }
|
public EntityInfo EntityInfo { get { return this.Context.EntityMaintenance.GetEntityInfo<T>(); } }
|
||||||
public int BulkCopy(List<T> datas)
|
public int BulkCopy(List<T> datas)
|
||||||
{
|
{
|
||||||
|
if (StaticConfig.SplitTableCreateTableFunc != null)
|
||||||
|
{
|
||||||
|
StaticConfig.SplitTableCreateTableFunc(typeof(T), datas?.Cast<object>()?.ToArray());
|
||||||
|
}
|
||||||
List<GroupModel> groupModels;
|
List<GroupModel> groupModels;
|
||||||
int result;
|
int result;
|
||||||
GroupDataList(datas, out groupModels, out result);
|
GroupDataList(datas, out groupModels, out result);
|
||||||
@ -28,6 +32,10 @@ namespace SqlSugar
|
|||||||
}
|
}
|
||||||
public async Task<int> BulkCopyAsync(List<T> datas)
|
public async Task<int> BulkCopyAsync(List<T> datas)
|
||||||
{
|
{
|
||||||
|
if (StaticConfig.SplitTableCreateTableFunc != null)
|
||||||
|
{
|
||||||
|
StaticConfig.SplitTableCreateTableFunc(typeof(T), datas?.Cast<object>()?.ToArray());
|
||||||
|
}
|
||||||
List<GroupModel> groupModels;
|
List<GroupModel> groupModels;
|
||||||
int result;
|
int result;
|
||||||
GroupDataList(datas, out groupModels, out result);
|
GroupDataList(datas, out groupModels, out result);
|
||||||
|
@ -17,7 +17,7 @@ namespace SqlSugar
|
|||||||
public DiffLogModel DiffModel { get; internal set; }
|
public DiffLogModel DiffModel { get; internal set; }
|
||||||
public bool IsOffIdentity { get; internal set; }
|
public bool IsOffIdentity { get; internal set; }
|
||||||
public bool IsInsertColumnsNull { get; internal set; }
|
public bool IsInsertColumnsNull { get; internal set; }
|
||||||
|
public bool IsMySqlIgnore { get; internal set; }
|
||||||
public int ExecuteCommand()
|
public int ExecuteCommand()
|
||||||
{
|
{
|
||||||
if (DataList.Count() == 1 && DataList.First() == null)
|
if (DataList.Count() == 1 && DataList.First() == null)
|
||||||
@ -35,7 +35,7 @@ namespace SqlSugar
|
|||||||
}
|
}
|
||||||
this.Context.Utilities.PageEach(DataList, PageSize, pageItem =>
|
this.Context.Utilities.PageEach(DataList, PageSize, pageItem =>
|
||||||
{
|
{
|
||||||
result += this.Context.Insertable(pageItem).AS(TableName).IgnoreColumnsNull(this.IsInsertColumnsNull).OffIdentity(IsOffIdentity).EnableDiffLogEventIF(IsEnableDiffLogEvent, DiffModel).InsertColumns(InsertColumns.ToArray()).ExecuteCommand();
|
result += this.Context.Insertable(pageItem).AS(TableName).MySqlIgnore(IsMySqlIgnore).IgnoreColumnsNull(this.IsInsertColumnsNull).OffIdentity(IsOffIdentity).EnableDiffLogEventIF(IsEnableDiffLogEvent, DiffModel).InsertColumns(InsertColumns.ToArray()).ExecuteCommand();
|
||||||
});
|
});
|
||||||
if (isNoTran)
|
if (isNoTran)
|
||||||
{
|
{
|
||||||
|
@ -510,6 +510,7 @@ namespace SqlSugar
|
|||||||
result.TableName = this.InsertBuilder.AsName;
|
result.TableName = this.InsertBuilder.AsName;
|
||||||
result.IsEnableDiffLogEvent = this.IsEnableDiffLogEvent;
|
result.IsEnableDiffLogEvent = this.IsEnableDiffLogEvent;
|
||||||
result.DiffModel = this.diffModel;
|
result.DiffModel = this.diffModel;
|
||||||
|
result.IsMySqlIgnore = this.InsertBuilder.MySqlIgnore;
|
||||||
result.IsOffIdentity = this.InsertBuilder.IsOffIdentity;
|
result.IsOffIdentity = this.InsertBuilder.IsOffIdentity;
|
||||||
if(this.InsertBuilder.DbColumnInfoList.Any())
|
if(this.InsertBuilder.DbColumnInfoList.Any())
|
||||||
result.InsertColumns = this.InsertBuilder.DbColumnInfoList.GroupBy(it => it.TableId).First().Select(it=>it.DbColumnName).ToList();
|
result.InsertColumns = this.InsertBuilder.DbColumnInfoList.GroupBy(it => it.TableId).First().Select(it=>it.DbColumnName).ToList();
|
||||||
@ -567,7 +568,16 @@ namespace SqlSugar
|
|||||||
this.InsertBuilder.MySqlIgnore = true;
|
this.InsertBuilder.MySqlIgnore = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public IInsertable<T> MySqlIgnore(bool isIgnore) {
|
||||||
|
if (isIgnore)
|
||||||
|
{
|
||||||
|
return MySqlIgnore();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
public IInsertable<T> InsertColumns(Expression<Func<T, object>> columns)
|
public IInsertable<T> InsertColumns(Expression<Func<T, object>> columns)
|
||||||
{
|
{
|
||||||
if (columns == null) return this;
|
if (columns == null) return this;
|
||||||
@ -763,6 +773,10 @@ namespace SqlSugar
|
|||||||
|
|
||||||
public SplitInsertable<T> SplitTable()
|
public SplitInsertable<T> SplitTable()
|
||||||
{
|
{
|
||||||
|
if (StaticConfig.SplitTableCreateTableFunc != null)
|
||||||
|
{
|
||||||
|
StaticConfig.SplitTableCreateTableFunc(typeof(T),this.InsertObjs);
|
||||||
|
}
|
||||||
UtilMethods.StartCustomSplitTable(this.Context, typeof(T));
|
UtilMethods.StartCustomSplitTable(this.Context, typeof(T));
|
||||||
var splitTableAttribute = typeof(T).GetCustomAttribute<SplitTableAttribute>();
|
var splitTableAttribute = typeof(T).GetCustomAttribute<SplitTableAttribute>();
|
||||||
if (splitTableAttribute != null)
|
if (splitTableAttribute != null)
|
||||||
|
@ -323,7 +323,12 @@ namespace SqlSugar
|
|||||||
var reslt = method.Invoke(QueryableObj, new object[] { });
|
var reslt = method.Invoke(QueryableObj, new object[] { });
|
||||||
return Convert.ToBoolean(reslt);
|
return Convert.ToBoolean(reslt);
|
||||||
}
|
}
|
||||||
|
public int Count()
|
||||||
|
{
|
||||||
|
var method = QueryableObj.GetType().GetMyMethod("Count", 0);
|
||||||
|
var reslt = method.Invoke(QueryableObj, new object[] { });
|
||||||
|
return Convert.ToInt32(reslt);
|
||||||
|
}
|
||||||
public object ToTree(string childPropertyName, string parentIdPropertyName, object rootValue, string primaryKeyPropertyName)
|
public object ToTree(string childPropertyName, string parentIdPropertyName, object rootValue, string primaryKeyPropertyName)
|
||||||
{
|
{
|
||||||
var method = QueryableObj.GetType().GetMyMethod("ToTree", 4,typeof(string),typeof(string),typeof(object),typeof(string));
|
var method = QueryableObj.GetType().GetMyMethod("ToTree", 4,typeof(string),typeof(string),typeof(object),typeof(string));
|
||||||
@ -379,6 +384,12 @@ namespace SqlSugar
|
|||||||
var reslt = method.Invoke(QueryableObj, new object[] { });
|
var reslt = method.Invoke(QueryableObj, new object[] { });
|
||||||
return await (Task<bool>) reslt;
|
return await (Task<bool>) reslt;
|
||||||
}
|
}
|
||||||
|
public async Task<int> CountAsync()
|
||||||
|
{
|
||||||
|
var method = QueryableObj.GetType().GetMyMethod("CountAsync", 0);
|
||||||
|
var reslt = method.Invoke(QueryableObj, new object[] { });
|
||||||
|
return await (Task<int>)reslt;
|
||||||
|
}
|
||||||
public async Task<object> InSingleAsync(object pkValue)
|
public async Task<object> InSingleAsync(object pkValue)
|
||||||
{
|
{
|
||||||
var method = QueryableObj.GetType().GetMyMethod("InSingleAsync", 1);
|
var method = QueryableObj.GetType().GetMyMethod("InSingleAsync", 1);
|
||||||
|
@ -121,7 +121,11 @@ namespace SqlSugar
|
|||||||
this.QueryBuilder.Includes == null &&
|
this.QueryBuilder.Includes == null &&
|
||||||
this.QueryBuilder.IsDistinct == false)
|
this.QueryBuilder.IsDistinct == false)
|
||||||
{
|
{
|
||||||
|
if (StaticConfig.EnableAot)
|
||||||
|
{
|
||||||
|
var sqlobj = this.Clone().Select<int>(" COUNT(1) ").ToSql();
|
||||||
|
return this.Context.Ado.GetInt(sqlobj.Key,sqlobj.Value);
|
||||||
|
}
|
||||||
return this.Clone().Select<int>(" COUNT(1) ").ToList().FirstOrDefault();
|
return this.Clone().Select<int>(" COUNT(1) ").ToList().FirstOrDefault();
|
||||||
}
|
}
|
||||||
MappingTableList expMapping;
|
MappingTableList expMapping;
|
||||||
|
@ -1885,8 +1885,12 @@ namespace SqlSugar
|
|||||||
var entityType = typeof(TResult);
|
var entityType = typeof(TResult);
|
||||||
bool isChangeQueryableSlave = GetIsSlaveQuery();
|
bool isChangeQueryableSlave = GetIsSlaveQuery();
|
||||||
bool isChangeQueryableMasterSlave = GetIsMasterQuery();
|
bool isChangeQueryableMasterSlave = GetIsMasterQuery();
|
||||||
var dataReader = this.Db.GetDataReader(sqlObj.Key, sqlObj.Value.ToArray());
|
string sqlString = sqlObj.Key;
|
||||||
|
SugarParameter[] parameters = sqlObj.Value.ToArray();
|
||||||
|
var dataReader = this.Db.GetDataReader(sqlString, parameters);
|
||||||
|
this.Db.GetDataBefore(sqlString, parameters);
|
||||||
result = GetData<TResult>(isComplexModel, entityType, dataReader);
|
result = GetData<TResult>(isComplexModel, entityType, dataReader);
|
||||||
|
this.Db.GetDataAfter(sqlString, parameters);
|
||||||
RestChangeMasterQuery(isChangeQueryableMasterSlave);
|
RestChangeMasterQuery(isChangeQueryableMasterSlave);
|
||||||
RestChangeSlaveQuery(isChangeQueryableSlave);
|
RestChangeSlaveQuery(isChangeQueryableSlave);
|
||||||
return result;
|
return result;
|
||||||
@ -1898,8 +1902,12 @@ namespace SqlSugar
|
|||||||
var entityType = typeof(TResult);
|
var entityType = typeof(TResult);
|
||||||
bool isChangeQueryableSlave = GetIsSlaveQuery();
|
bool isChangeQueryableSlave = GetIsSlaveQuery();
|
||||||
bool isChangeQueryableMasterSlave = GetIsMasterQuery();
|
bool isChangeQueryableMasterSlave = GetIsMasterQuery();
|
||||||
var dataReader = await this.Db.GetDataReaderAsync(sqlObj.Key, sqlObj.Value.ToArray());
|
string sqlString = sqlObj.Key;
|
||||||
|
SugarParameter[] parameters = sqlObj.Value.ToArray();
|
||||||
|
var dataReader = await this.Db.GetDataReaderAsync(sqlString, parameters);
|
||||||
|
this.Db.GetDataBefore(sqlString, parameters);
|
||||||
result = await GetDataAsync<TResult>(isComplexModel, entityType, dataReader);
|
result = await GetDataAsync<TResult>(isComplexModel, entityType, dataReader);
|
||||||
|
this.Db.GetDataAfter(sqlString, parameters);
|
||||||
RestChangeMasterQuery(isChangeQueryableMasterSlave);
|
RestChangeMasterQuery(isChangeQueryableMasterSlave);
|
||||||
RestChangeSlaveQuery(isChangeQueryableSlave);
|
RestChangeSlaveQuery(isChangeQueryableSlave);
|
||||||
return result;
|
return result;
|
||||||
|
@ -460,15 +460,31 @@ namespace SqlSugar
|
|||||||
if (isSameName||ChildType.IsInterface)
|
if (isSameName||ChildType.IsInterface)
|
||||||
{
|
{
|
||||||
var mysql = GetSql(exp, isSingle);
|
var mysql = GetSql(exp, isSingle);
|
||||||
if (ChildType.IsInterface)
|
if (ChildType.IsInterface&&item.IsJoinQuery==true)
|
||||||
{
|
{
|
||||||
foreach (var joinInfoItem in this.JoinQueryInfos.Where(it => it.EntityType.GetInterfaces().Any(z=>z==ChildType)))
|
foreach (var joinInfoItem in this.JoinQueryInfos.Where(it => it.EntityType.GetInterfaces().Any(z=>z==ChildType)))
|
||||||
{
|
{
|
||||||
var addSql = mysql.Replace(itName, this.Builder.GetTranslationColumnName(joinInfoItem.ShortName) + ".");
|
var addSql = mysql.Replace(itName, this.Builder.GetTranslationColumnName(joinInfoItem.ShortName) + ".");
|
||||||
addSql = ReplaceFilterColumnName(addSql, joinInfoItem.EntityType,joinInfoItem.ShortName);
|
addSql = ReplaceFilterColumnName(addSql, joinInfoItem.EntityType,joinInfoItem.ShortName);
|
||||||
joinInfoItem.JoinWhere += (" AND " + Regex.Replace(addSql, "^ (WHERE|AND) ", ""));
|
joinInfoItem.JoinWhere += ( " AND " + Regex.Replace(addSql, "^ (WHERE|AND) ", ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ChildType.IsInterface && item.IsJoinQuery == false)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var addSql = mysql.Replace(itName, this.Builder.GetTranslationColumnName(TableShortName) + ".");
|
||||||
|
addSql = ReplaceFilterColumnName(addSql, EntityType, TableShortName);
|
||||||
|
var andOrWhere = this.WhereInfos.Any() ? " AND " : "WHERE";
|
||||||
|
this.WhereInfos.Add(andOrWhere + Regex.Replace(addSql, "^ (WHERE|AND) ", ""));
|
||||||
|
}
|
||||||
|
foreach (var joinInfoItem in this.JoinQueryInfos.Where(it => it.EntityType.GetInterfaces().Any(z => z == ChildType)))
|
||||||
|
{
|
||||||
|
var addSql = mysql.Replace(itName, this.Builder.GetTranslationColumnName(joinInfoItem.ShortName) + ".");
|
||||||
|
addSql = ReplaceFilterColumnName(addSql, joinInfoItem.EntityType, joinInfoItem.ShortName);
|
||||||
|
this.WhereInfos.Add (" AND " + Regex.Replace(addSql, "^ (WHERE|AND) ", ""));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var joinInfoItem in this.JoinQueryInfos.Where(it => it.TableName == entityInfo.DbTableName))
|
foreach (var joinInfoItem in this.JoinQueryInfos.Where(it => it.TableName == entityInfo.DbTableName))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -425,6 +426,10 @@ namespace SqlSugar
|
|||||||
}
|
}
|
||||||
else if (UtilMethods.IsNumber(type.Name))
|
else if (UtilMethods.IsNumber(type.Name))
|
||||||
{
|
{
|
||||||
|
if (value is decimal v)
|
||||||
|
{
|
||||||
|
return v.ToString(UtilConstants.EnCultureInfo);
|
||||||
|
}
|
||||||
if (value.ObjToString().Contains(","))
|
if (value.ObjToString().Contains(","))
|
||||||
{
|
{
|
||||||
return $"'{value}'";
|
return $"'{value}'";
|
||||||
|
@ -94,6 +94,10 @@ namespace SqlSugar
|
|||||||
public Action<object, DataFilterModel> DataExecuting { get; set; }
|
public Action<object, DataFilterModel> DataExecuting { get; set; }
|
||||||
public Action<object, DataFilterModel> DataChangesExecuted { get; set; }
|
public Action<object, DataFilterModel> DataChangesExecuted { get; set; }
|
||||||
public Action<object, DataAfterModel> DataExecuted { get; set; }
|
public Action<object, DataAfterModel> DataExecuted { get; set; }
|
||||||
|
public Action<IDbConnection> CheckConnectionExecuting { get; set; }
|
||||||
|
public Action<IDbConnection,TimeSpan> CheckConnectionExecuted { get; set; }
|
||||||
|
public Action<string, SugarParameter[]> OnGetDataReadering { get; set; }
|
||||||
|
public Action<string, SugarParameter[], TimeSpan> OnGetDataReadered { get; set; }
|
||||||
}
|
}
|
||||||
public class ConfigureExternalServices
|
public class ConfigureExternalServices
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,7 @@ namespace SqlSugar
|
|||||||
public static Action<ISqlSugarClient> CompleteDbFunc;
|
public static Action<ISqlSugarClient> CompleteDbFunc;
|
||||||
|
|
||||||
public static Func<List<SplitTableInfo>> SplitTableGetTablesFunc;
|
public static Func<List<SplitTableInfo>> SplitTableGetTablesFunc;
|
||||||
|
public static Action<Type,object[]> SplitTableCreateTableFunc;
|
||||||
|
|
||||||
public static bool Check_StringIdentity = true;
|
public static bool Check_StringIdentity = true;
|
||||||
public static bool EnableAllWhereIF = false;
|
public static bool EnableAllWhereIF = false;
|
||||||
|
@ -18,11 +18,15 @@ namespace SqlSugar
|
|||||||
IDataParameter[] ToIDbDataParameter(params SugarParameter[] pars);
|
IDataParameter[] ToIDbDataParameter(params SugarParameter[] pars);
|
||||||
SugarParameter[] GetParameters(object obj, PropertyInfo[] propertyInfo = null);
|
SugarParameter[] GetParameters(object obj, PropertyInfo[] propertyInfo = null);
|
||||||
SqlSugarProvider Context { get; set; }
|
SqlSugarProvider Context { get; set; }
|
||||||
|
void CheckConnectionAfter(IDbConnection Connection);
|
||||||
|
void CheckConnectionBefore(IDbConnection Connection);
|
||||||
void ExecuteBefore(string sql, SugarParameter[] pars);
|
void ExecuteBefore(string sql, SugarParameter[] pars);
|
||||||
void ExecuteAfter(string sql, SugarParameter[] pars);
|
void ExecuteAfter(string sql, SugarParameter[] pars);
|
||||||
|
void GetDataBefore(string sql, SugarParameter[] parameters);
|
||||||
|
void GetDataAfter(string sql, SugarParameter[] parameters);
|
||||||
bool IsAnyTran();
|
bool IsAnyTran();
|
||||||
bool IsNoTran();
|
bool IsNoTran();
|
||||||
bool IsEnableLogEvent{get;set;}
|
bool IsEnableLogEvent { get; set; }
|
||||||
StackTraceInfo SqlStackTrace { get; }
|
StackTraceInfo SqlStackTrace { get; }
|
||||||
IDataParameterCollection DataReaderParameters { get; set; }
|
IDataParameterCollection DataReaderParameters { get; set; }
|
||||||
CommandType CommandType { get; set; }
|
CommandType CommandType { get; set; }
|
||||||
@ -31,6 +35,7 @@ namespace SqlSugar
|
|||||||
bool IsClearParameters { get; set; }
|
bool IsClearParameters { get; set; }
|
||||||
int CommandTimeOut { get; set; }
|
int CommandTimeOut { get; set; }
|
||||||
TimeSpan SqlExecutionTime { get; }
|
TimeSpan SqlExecutionTime { get; }
|
||||||
|
TimeSpan ConnectionExecutionTime { get; }
|
||||||
int SqlExecuteCount { get; }
|
int SqlExecuteCount { get; }
|
||||||
IDbBind DbBind { get; }
|
IDbBind DbBind { get; }
|
||||||
void SetCommandToAdapter(IDataAdapter adapter, DbCommand command);
|
void SetCommandToAdapter(IDataAdapter adapter, DbCommand command);
|
||||||
@ -79,7 +84,7 @@ namespace SqlSugar
|
|||||||
|
|
||||||
Task<int> ExecuteCommandAsync(string sql, params SugarParameter[] parameters);
|
Task<int> ExecuteCommandAsync(string sql, params SugarParameter[] parameters);
|
||||||
Task<int> ExecuteCommandAsync(string sql, object parameters);
|
Task<int> ExecuteCommandAsync(string sql, object parameters);
|
||||||
Task<int> ExecuteCommandAsync(string sql, object parameters,CancellationToken cancellationToken);
|
Task<int> ExecuteCommandAsync(string sql, object parameters, CancellationToken cancellationToken);
|
||||||
Task<int> ExecuteCommandAsync(string sql, List<SugarParameter> parameters);
|
Task<int> ExecuteCommandAsync(string sql, List<SugarParameter> parameters);
|
||||||
|
|
||||||
string GetString(string sql, object parameters);
|
string GetString(string sql, object parameters);
|
||||||
@ -99,9 +104,9 @@ namespace SqlSugar
|
|||||||
Task<int> GetIntAsync(string sql, List<SugarParameter> parameters);
|
Task<int> GetIntAsync(string sql, List<SugarParameter> parameters);
|
||||||
|
|
||||||
|
|
||||||
long GetLong(string sql, object pars=null);
|
long GetLong(string sql, object pars = null);
|
||||||
|
|
||||||
Task<long> GetLongAsync(string sql, object pars=null);
|
Task<long> GetLongAsync(string sql, object pars = null);
|
||||||
|
|
||||||
|
|
||||||
Double GetDouble(string sql, object parameters);
|
Double GetDouble(string sql, object parameters);
|
||||||
@ -132,12 +137,12 @@ namespace SqlSugar
|
|||||||
Task<DateTime> GetDateTimeAsync(string sql, List<SugarParameter> parameters);
|
Task<DateTime> GetDateTimeAsync(string sql, List<SugarParameter> parameters);
|
||||||
|
|
||||||
|
|
||||||
Tuple<List<T>, List<T2>> SqlQuery<T,T2>(string sql, object parameters = null);
|
Tuple<List<T>, List<T2>> SqlQuery<T, T2>(string sql, object parameters = null);
|
||||||
Tuple<List<T>, List<T2>, List<T3>> SqlQuery<T, T2,T3>(string sql, object parameters = null);
|
Tuple<List<T>, List<T2>, List<T3>> SqlQuery<T, T2, T3>(string sql, object parameters = null);
|
||||||
Tuple<List<T>, List<T2>, List<T3>,List<T4>> SqlQuery<T,T2,T3,T4>(string sql, object parameters = null);
|
Tuple<List<T>, List<T2>, List<T3>, List<T4>> SqlQuery<T, T2, T3, T4>(string sql, object parameters = null);
|
||||||
Tuple<List<T>, List<T2>, List<T3>, List<T4>, List<T5>> SqlQuery<T, T2, T3, T4,T5>(string sql, object parameters = null);
|
Tuple<List<T>, List<T2>, List<T3>, List<T4>, List<T5>> SqlQuery<T, T2, T3, T4, T5>(string sql, object parameters = null);
|
||||||
Tuple<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>> SqlQuery<T, T2, T3, T4, T5,T6>(string sql, object parameters = null);
|
Tuple<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>> SqlQuery<T, T2, T3, T4, T5, T6>(string sql, object parameters = null);
|
||||||
Tuple<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>, List<T7>> SqlQuery<T, T2, T3, T4, T5, T6,T7>(string sql, object parameters = null);
|
Tuple<List<T>, List<T2>, List<T3>, List<T4>, List<T5>, List<T6>, List<T7>> SqlQuery<T, T2, T3, T4, T5, T6, T7>(string sql, object parameters = null);
|
||||||
|
|
||||||
Task<Tuple<List<T>, List<T2>>> SqlQueryAsync<T, T2>(string sql, object parameters = null);
|
Task<Tuple<List<T>, List<T2>>> SqlQueryAsync<T, T2>(string sql, object parameters = null);
|
||||||
Task<Tuple<List<T>, List<T2>, List<T3>>> SqlQueryAsync<T, T2, T3>(string sql, object parameters = null);
|
Task<Tuple<List<T>, List<T2>, List<T3>>> SqlQueryAsync<T, T2, T3>(string sql, object parameters = null);
|
||||||
@ -153,7 +158,7 @@ namespace SqlSugar
|
|||||||
List<T> MasterSqlQuery<T>(string sql, object parameters = null);
|
List<T> MasterSqlQuery<T>(string sql, object parameters = null);
|
||||||
|
|
||||||
Task<List<T>> SqlQueryAsync<T>(string sql, object parameters = null);
|
Task<List<T>> SqlQueryAsync<T>(string sql, object parameters = null);
|
||||||
Task<List<T>> SqlQueryAsync<T>(string sql, object parameters,CancellationToken token);
|
Task<List<T>> SqlQueryAsync<T>(string sql, object parameters, CancellationToken token);
|
||||||
Task<List<T>> SqlQueryAsync<T>(string sql, List<SugarParameter> parameters);
|
Task<List<T>> SqlQueryAsync<T>(string sql, List<SugarParameter> parameters);
|
||||||
Task<List<T>> SqlQueryAsync<T>(string sql, params SugarParameter[] parameters);
|
Task<List<T>> SqlQueryAsync<T>(string sql, params SugarParameter[] parameters);
|
||||||
|
|
||||||
@ -191,6 +196,6 @@ namespace SqlSugar
|
|||||||
Task<DbResult<bool>> UseTranAsync(Func<Task> action, Action<Exception> errorCallBack = null);
|
Task<DbResult<bool>> UseTranAsync(Func<Task> action, Action<Exception> errorCallBack = null);
|
||||||
Task<DbResult<T>> UseTranAsync<T>(Func<Task<T>> action, Action<Exception> errorCallBack = null);
|
Task<DbResult<T>> UseTranAsync<T>(Func<Task<T>> action, Action<Exception> errorCallBack = null);
|
||||||
IAdo UseStoredProcedure();
|
IAdo UseStoredProcedure();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ namespace SqlSugar
|
|||||||
SplitInsertable<T> SplitTable(SplitType splitType);
|
SplitInsertable<T> SplitTable(SplitType splitType);
|
||||||
void AddQueue();
|
void AddQueue();
|
||||||
IInsertable<T> MySqlIgnore();
|
IInsertable<T> MySqlIgnore();
|
||||||
|
IInsertable<T> MySqlIgnore(bool isIgnore);
|
||||||
IInsertable<T> PostgreSQLConflictNothing(string[] columns);
|
IInsertable<T> PostgreSQLConflictNothing(string[] columns);
|
||||||
IInsertable<T> OffIdentity();
|
IInsertable<T> OffIdentity();
|
||||||
IInsertable<T> OffIdentity(bool isSetOn);
|
IInsertable<T> OffIdentity(bool isSetOn);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Dynamic;
|
using System.Dynamic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
namespace SqlSugar
|
namespace SqlSugar
|
||||||
@ -62,7 +63,7 @@ namespace SqlSugar
|
|||||||
typeof(short),
|
typeof(short),
|
||||||
typeof(ushort),
|
typeof(ushort),
|
||||||
};
|
};
|
||||||
|
internal static CultureInfo EnCultureInfo = new CultureInfo("en");
|
||||||
|
|
||||||
internal static string[] DateTypeStringList = new string[]
|
internal static string[] DateTypeStringList = new string[]
|
||||||
{
|
{
|
||||||
|
@ -109,6 +109,10 @@ namespace SqlSugar
|
|||||||
{
|
{
|
||||||
return string.Join("|",thisValue as byte[]);
|
return string.Join("|",thisValue as byte[]);
|
||||||
}
|
}
|
||||||
|
if (thisValue!=null&&thisValue?.GetType()?.Name == "DateOnly")
|
||||||
|
{
|
||||||
|
return Convert.ToDateTime(thisValue.ToString()).ToString("yyyy-MM-dd");
|
||||||
|
}
|
||||||
if (thisValue != null) return thisValue.ToString().Trim();
|
if (thisValue != null) return thisValue.ToString().Trim();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -662,6 +662,10 @@ namespace SqlSugar
|
|||||||
OnLogExecuted=it.AopEvents?.OnLogExecuted,
|
OnLogExecuted=it.AopEvents?.OnLogExecuted,
|
||||||
OnLogExecuting= it.AopEvents?.OnLogExecuting,
|
OnLogExecuting= it.AopEvents?.OnLogExecuting,
|
||||||
DataExecuted = it.AopEvents?.DataExecuted,
|
DataExecuted = it.AopEvents?.DataExecuted,
|
||||||
|
CheckConnectionExecuted = it.AopEvents?.CheckConnectionExecuted,
|
||||||
|
CheckConnectionExecuting = it.AopEvents?.CheckConnectionExecuting,
|
||||||
|
OnGetDataReadered= it.AopEvents?.OnGetDataReadered,
|
||||||
|
OnGetDataReadering = it.AopEvents?.OnGetDataReadering,
|
||||||
},
|
},
|
||||||
ConfigId = it.ConfigId,
|
ConfigId = it.ConfigId,
|
||||||
ConfigureExternalServices =it.ConfigureExternalServices==null?null:new ConfigureExternalServices() {
|
ConfigureExternalServices =it.ConfigureExternalServices==null?null:new ConfigureExternalServices() {
|
||||||
@ -1579,7 +1583,7 @@ namespace SqlSugar
|
|||||||
var result = sqlObj.Key;
|
var result = sqlObj.Key;
|
||||||
if (sqlObj.Value != null)
|
if (sqlObj.Value != null)
|
||||||
{
|
{
|
||||||
foreach (var item in sqlObj.Value.OrderByDescending(it => it.ParameterName.Length))
|
foreach (var item in UtilMethods.CopySugarParameters(sqlObj.Value).OrderByDescending(it => it.ParameterName.Length))
|
||||||
{
|
{
|
||||||
if (item.ParameterName.StartsWith(":")&&!result.Contains(item.ParameterName))
|
if (item.ParameterName.StartsWith(":")&&!result.Contains(item.ParameterName))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user