mirror of
https://gitee.com/dotnetchina/SqlSugar.git
synced 2026-01-21 18:48:27 +08:00
Code optimization
This commit is contained in:
@@ -0,0 +1,573 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Reflection;
|
||||
using System.Dynamic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SqlSugar
|
||||
{
|
||||
|
||||
public partial class QueryableProvider<T> : QueryableAccessory, ISugarQueryable<T>
|
||||
{
|
||||
public virtual int Count()
|
||||
{
|
||||
if (this.QueryBuilder.Skip == null &&
|
||||
this.QueryBuilder.Take == null &&
|
||||
this.QueryBuilder.OrderByValue == null &&
|
||||
this.QueryBuilder.PartitionByValue == null &&
|
||||
this.QueryBuilder.SelectValue == null &&
|
||||
this.QueryBuilder.Includes == null &&
|
||||
this.QueryBuilder.IsDistinct == false)
|
||||
{
|
||||
|
||||
return this.Clone().Select<int>(" COUNT(1) ").ToList().FirstOrDefault();
|
||||
}
|
||||
MappingTableList expMapping;
|
||||
int result;
|
||||
_CountBegin(out expMapping, out result);
|
||||
if (IsCache)
|
||||
{
|
||||
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
|
||||
result = CacheSchemeMain.GetOrCreate<int>(cacheService, this.QueryBuilder, () => { return GetCount(); }, CacheTime, this.Context, CacheKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = GetCount();
|
||||
}
|
||||
_CountEnd(expMapping);
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual int Count(Expression<Func<T, bool>> expression)
|
||||
{
|
||||
_Where(expression);
|
||||
var result = Count();
|
||||
this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last());
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual TResult Max<TResult>(string maxField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.MaxTemplate, maxField));
|
||||
var result = this._ToList<TResult>().SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
public virtual TResult Max<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _Max<TResult>(expression);
|
||||
}
|
||||
|
||||
public virtual TResult Min<TResult>(string minField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.MinTemplate, minField));
|
||||
var result = this._ToList<TResult>().SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
public virtual TResult Min<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _Min<TResult>(expression);
|
||||
}
|
||||
|
||||
public virtual TResult Sum<TResult>(string sumField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.SumTemplate, sumField));
|
||||
var result = this._ToList<TResult>().SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
public virtual TResult Sum<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _Sum<TResult>(expression);
|
||||
}
|
||||
|
||||
public virtual TResult Avg<TResult>(string avgField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.AvgTemplate, avgField));
|
||||
var result = this._ToList<TResult>().SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
public virtual TResult Avg<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _Avg<TResult>(expression);
|
||||
}
|
||||
public virtual T[] ToArray()
|
||||
{
|
||||
|
||||
var result = this.ToList();
|
||||
if (result.HasValue())
|
||||
return result.ToArray();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual string ToJson()
|
||||
{
|
||||
if (IsCache)
|
||||
{
|
||||
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
|
||||
var result = CacheSchemeMain.GetOrCreate<string>(cacheService, this.QueryBuilder, () =>
|
||||
{
|
||||
return this.Context.Utilities.SerializeObject(this.ToList(), typeof(T));
|
||||
}, CacheTime, this.Context, CacheKey);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.Context.Utilities.SerializeObject(this.ToList(), typeof(T));
|
||||
}
|
||||
}
|
||||
public virtual string ToJsonPage(int pageIndex, int pageSize)
|
||||
{
|
||||
return this.Context.Utilities.SerializeObject(this.ToPageList(pageIndex, pageSize), typeof(T));
|
||||
}
|
||||
public virtual string ToJsonPage(int pageIndex, int pageSize, ref int totalNumber)
|
||||
{
|
||||
return this.Context.Utilities.SerializeObject(this.ToPageList(pageIndex, pageSize, ref totalNumber), typeof(T));
|
||||
}
|
||||
public virtual DataTable ToPivotTable<TColumn, TRow, TData>(Func<T, TColumn> columnSelector, Expression<Func<T, TRow>> rowSelector, Func<IEnumerable<T>, TData> dataSelector)
|
||||
{
|
||||
return this.ToList().ToPivotTable(columnSelector, rowSelector, dataSelector);
|
||||
}
|
||||
public virtual List<dynamic> ToPivotList<TColumn, TRow, TData>(Func<T, TColumn> columnSelector, Expression<Func<T, TRow>> rowSelector, Func<IEnumerable<T>, TData> dataSelector)
|
||||
{
|
||||
return this.ToList().ToPivotList(columnSelector, rowSelector, dataSelector);
|
||||
}
|
||||
public virtual string ToPivotJson<TColumn, TRow, TData>(Func<T, TColumn> columnSelector, Expression<Func<T, TRow>> rowSelector, Func<IEnumerable<T>, TData> dataSelector)
|
||||
{
|
||||
var list = this.ToPivotList(columnSelector, rowSelector, dataSelector);
|
||||
return this.Context.Utilities.SerializeObject(list);
|
||||
}
|
||||
public List<T> ToChildList(Expression<Func<T, object>> parentIdExpression, object primaryKeyValue, bool isContainOneself = true)
|
||||
{
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var pk = GetTreeKey(entity);
|
||||
var list = this.ToList();
|
||||
return GetChildList(parentIdExpression, pk, list, primaryKeyValue, isContainOneself);
|
||||
}
|
||||
|
||||
public List<T> ToParentList(Expression<Func<T, object>> parentIdExpression, object primaryKeyValue)
|
||||
{
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var isTreeKey = entity.Columns.Any(it => it.IsTreeKey);
|
||||
if (isTreeKey)
|
||||
{
|
||||
return _ToParentListByTreeKey(parentIdExpression, primaryKeyValue);
|
||||
}
|
||||
List<T> result = new List<T>() { };
|
||||
Check.Exception(entity.Columns.Where(it => it.IsPrimarykey).Count() == 0, "No Primary key");
|
||||
var parentIdName = UtilConvert.ToMemberExpression((parentIdExpression as LambdaExpression).Body).Member.Name;
|
||||
var ParentInfo = entity.Columns.First(it => it.PropertyName == parentIdName);
|
||||
var parentPropertyName = ParentInfo.DbColumnName;
|
||||
var tableName = this.QueryBuilder.GetTableNameString;
|
||||
if (this.QueryBuilder.IsSingle() == false)
|
||||
{
|
||||
if (this.QueryBuilder.JoinQueryInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
if (this.QueryBuilder.EasyJoinInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
}
|
||||
var current = this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).InSingle(primaryKeyValue);
|
||||
if (current != null)
|
||||
{
|
||||
result.Add(current);
|
||||
object parentId = ParentInfo.PropertyInfo.GetValue(current, null);
|
||||
int i = 0;
|
||||
while (parentId != null && this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).In(parentId).Any())
|
||||
{
|
||||
Check.Exception(i > 100, ErrorMessage.GetThrowMessage("Dead cycle", "出现死循环或超出循环上限(100),检查最顶层的ParentId是否是null或者0"));
|
||||
var parent = this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).InSingle(parentId);
|
||||
result.Add(parent);
|
||||
parentId = ParentInfo.PropertyInfo.GetValue(parent, null);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<T> ToTree(Expression<Func<T, IEnumerable<object>>> childListExpression, Expression<Func<T, object>> parentIdExpression, object rootValue)
|
||||
{
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var pk = GetTreeKey(entity);
|
||||
var list = this.ToList();
|
||||
return GetTreeRoot(childListExpression, parentIdExpression, pk, list, rootValue);
|
||||
}
|
||||
|
||||
public virtual DataTable ToDataTable()
|
||||
{
|
||||
QueryBuilder.ResultType = typeof(SugarCacheDataTable);
|
||||
InitMapping();
|
||||
var sqlObj = this.ToSql();
|
||||
RestoreMapping();
|
||||
DataTable result = null;
|
||||
bool isChangeQueryableMasterSlave = GetIsMasterQuery();
|
||||
bool isChangeQueryableSlave = GetIsSlaveQuery();
|
||||
if (IsCache)
|
||||
{
|
||||
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
|
||||
result = CacheSchemeMain.GetOrCreate<DataTable>(cacheService, this.QueryBuilder, () => { return this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); }, CacheTime, this.Context, CacheKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray());
|
||||
}
|
||||
RestChangeMasterQuery(isChangeQueryableMasterSlave);
|
||||
RestChangeSlaveQuery(isChangeQueryableSlave);
|
||||
return result;
|
||||
}
|
||||
public virtual DataTable ToDataTablePage(int pageIndex, int pageSize)
|
||||
{
|
||||
if (pageIndex == 0)
|
||||
pageIndex = 1;
|
||||
if (QueryBuilder.PartitionByValue.HasValue())
|
||||
{
|
||||
QueryBuilder.ExternalPageIndex = pageIndex;
|
||||
QueryBuilder.ExternalPageSize = pageSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
QueryBuilder.Skip = (pageIndex - 1) * pageSize;
|
||||
QueryBuilder.Take = pageSize;
|
||||
}
|
||||
return ToDataTable();
|
||||
}
|
||||
public virtual DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber)
|
||||
{
|
||||
_RestoreMapping = false;
|
||||
totalNumber = this.Clone().Count();
|
||||
_RestoreMapping = true;
|
||||
var result = this.Clone().ToDataTablePage(pageIndex, pageSize);
|
||||
return result;
|
||||
}
|
||||
public virtual DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber, ref int totalPage)
|
||||
{
|
||||
var result = ToDataTablePage(pageIndex, pageSize, ref totalNumber);
|
||||
totalPage = (totalNumber + pageSize - 1) / pageSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Dictionary<string, object> ToDictionary(Expression<Func<T, object>> key, Expression<Func<T, object>> value)
|
||||
{
|
||||
this.QueryBuilder.ResultType = typeof(SugarCacheDictionary);
|
||||
var keyName = QueryBuilder.GetExpressionValue(key, ResolveExpressType.FieldSingle).GetResultString();
|
||||
var valueName = QueryBuilder.GetExpressionValue(value, ResolveExpressType.FieldSingle).GetResultString();
|
||||
if (this.QueryBuilder.IsSingle() == false)
|
||||
{
|
||||
keyName = this.QueryBuilder.TableShortName + "." + keyName;
|
||||
valueName = this.QueryBuilder.TableShortName + "." + valueName;
|
||||
}
|
||||
var result = this.Select<KeyValuePair<string, object>>(keyName + "," + valueName).ToList().ToDictionary(it => it.Key.ObjToString(), it => it.Value);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Dictionary<string, object>> ToDictionaryList()
|
||||
{
|
||||
var list = this.ToList();
|
||||
if (list == null)
|
||||
return null;
|
||||
else
|
||||
return this.Context.Utilities.DeserializeObject<List<Dictionary<string, object>>>(this.Context.Utilities.SerializeObject(list));
|
||||
}
|
||||
public async Task<List<Dictionary<string, object>>> ToDictionaryListAsync()
|
||||
{
|
||||
var list = await this.ToListAsync();
|
||||
if (list == null)
|
||||
return null;
|
||||
else
|
||||
return this.Context.Utilities.DeserializeObject<List<Dictionary<string, object>>>(this.Context.Utilities.SerializeObject(list));
|
||||
}
|
||||
|
||||
public virtual List<T> ToList()
|
||||
{
|
||||
InitMapping();
|
||||
return _ToList<T>();
|
||||
}
|
||||
public List<T> SetContext<ParameterT>(Expression<Func<T, object>> thisFiled, Expression<Func<object>> mappingFiled, ParameterT parameter)
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return new List<T>();
|
||||
}
|
||||
List<T> result = new List<T>();
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<ParameterT>();
|
||||
var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext<ParameterT>;
|
||||
var list = queryableContext.list;
|
||||
var pkName = "";
|
||||
if ((mappingFiled as LambdaExpression).Body is UnaryExpression)
|
||||
{
|
||||
pkName = (((mappingFiled as LambdaExpression).Body as UnaryExpression).Operand as MemberExpression).Member.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkName = ((mappingFiled as LambdaExpression).Body as MemberExpression).Member.Name;
|
||||
}
|
||||
var key = thisFiled.ToString() + mappingFiled.ToString() + typeof(ParameterT).FullName + typeof(T).FullName;
|
||||
var ids = list.Where(it => it != null).Select(it => it.GetType().GetProperty(pkName).GetValue(it)).Distinct().ToArray();
|
||||
if (queryableContext.TempChildLists == null)
|
||||
queryableContext.TempChildLists = new Dictionary<string, object>();
|
||||
if (list != null && queryableContext.TempChildLists.ContainsKey(key))
|
||||
{
|
||||
result = (List<T>)queryableContext.TempChildLists[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (queryableContext.TempChildLists == null)
|
||||
queryableContext.TempChildLists = new Dictionary<string, object>();
|
||||
this.Context.Utilities.PageEach(ids, 200, pageIds =>
|
||||
{
|
||||
result.AddRange(this.Clone().In(thisFiled, pageIds).ToList());
|
||||
});
|
||||
queryableContext.TempChildLists[key] = result;
|
||||
}
|
||||
var name = "";
|
||||
if ((thisFiled as LambdaExpression).Body is UnaryExpression)
|
||||
{
|
||||
name = (((thisFiled as LambdaExpression).Body as UnaryExpression).Operand as MemberExpression).Member.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = ((thisFiled as LambdaExpression).Body as MemberExpression).Member.Name;
|
||||
}
|
||||
var pkValue = parameter.GetType().GetProperty(pkName).GetValue(parameter);
|
||||
result = result.Where(it => it.GetType().GetProperty(name).GetValue(it).ObjToString() == pkValue.ObjToString()).ToList();
|
||||
return result;
|
||||
}
|
||||
public List<T> SetContext<ParameterT>(Expression<Func<T, object>> thisFiled1, Expression<Func<object>> mappingFiled1,
|
||||
Expression<Func<T, object>> thisFiled2, Expression<Func<object>> mappingFiled2,
|
||||
ParameterT parameter)
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return new List<T>();
|
||||
}
|
||||
var rightEntity = this.Context.EntityMaintenance.GetEntityInfo<ParameterT>();
|
||||
var leftEntity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
List<T> result = new List<T>();
|
||||
var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext<ParameterT>;
|
||||
var list = queryableContext.list;
|
||||
var key = thisFiled1.ToString() + mappingFiled1.ToString() +
|
||||
thisFiled2.ToString() + mappingFiled2.ToString() +
|
||||
typeof(ParameterT).FullName + typeof(T).FullName;
|
||||
MappingFieldsHelper<ParameterT> fieldsHelper = new MappingFieldsHelper<ParameterT>();
|
||||
var mappings = new List<MappingFieldsExpression>() {
|
||||
new MappingFieldsExpression(){
|
||||
LeftColumnExpression=thisFiled1,
|
||||
LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled1)),
|
||||
RightColumnExpression=mappingFiled1,
|
||||
RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled1))
|
||||
},
|
||||
new MappingFieldsExpression(){
|
||||
LeftColumnExpression=thisFiled2,
|
||||
LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled2)),
|
||||
RightColumnExpression=mappingFiled2,
|
||||
RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled2))
|
||||
}
|
||||
};
|
||||
var conditionals = fieldsHelper.GetMppingSql(list.Cast<object>().ToList(), mappings);
|
||||
if (queryableContext.TempChildLists == null)
|
||||
queryableContext.TempChildLists = new Dictionary<string, object>();
|
||||
if (list != null && queryableContext.TempChildLists.ContainsKey(key))
|
||||
{
|
||||
result = (List<T>)queryableContext.TempChildLists[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.Clone().Where(conditionals, true).ToList();
|
||||
queryableContext.TempChildLists[key] = result;
|
||||
}
|
||||
List<object> listObj = result.Select(it => (object)it).ToList();
|
||||
object obj = (object)parameter;
|
||||
var newResult = fieldsHelper.GetSetList(obj, listObj, mappings).Select(it => (T)it).ToList();
|
||||
return newResult;
|
||||
}
|
||||
|
||||
public virtual void ForEach(Action<T> action, int singleMaxReads = 300, System.Threading.CancellationTokenSource cancellationTokenSource = null)
|
||||
{
|
||||
Check.Exception(this.QueryBuilder.Skip > 0 || this.QueryBuilder.Take > 0, ErrorMessage.GetThrowMessage("no support Skip take, use PageForEach", "不支持Skip Take,请使用 Queryale.PageForEach"));
|
||||
var totalNumber = 0;
|
||||
var totalPage = 1;
|
||||
for (int i = 1; i <= totalPage; i++)
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
var queryable = this.Clone();
|
||||
var page =
|
||||
totalPage == 1 ?
|
||||
queryable.ToPageList(i, singleMaxReads, ref totalNumber, ref totalPage) :
|
||||
queryable.ToPageList(i, singleMaxReads);
|
||||
foreach (var item in page)
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
action.Invoke(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ForEachByPage(Action<T> action, int pageIndex, int pageSize, ref int totalNumber, int singleMaxReads = 300, System.Threading.CancellationTokenSource cancellationTokenSource = null)
|
||||
{
|
||||
int count = this.Clone().Count();
|
||||
if (count > 0)
|
||||
{
|
||||
if (pageSize > singleMaxReads && count - ((pageIndex - 1) * pageSize) > singleMaxReads)
|
||||
{
|
||||
Int32 Skip = (pageIndex - 1) * pageSize;
|
||||
Int32 NowCount = count - Skip;
|
||||
Int32 number = 0;
|
||||
if (NowCount > pageSize) NowCount = pageSize;
|
||||
while (NowCount > 0)
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
if (number + singleMaxReads > pageSize) singleMaxReads = NowCount;
|
||||
foreach (var item in this.Clone().Skip(Skip).Take(singleMaxReads).ToList())
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
action.Invoke(item);
|
||||
}
|
||||
NowCount -= singleMaxReads;
|
||||
Skip += singleMaxReads;
|
||||
number += singleMaxReads;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
foreach (var item in this.Clone().ToPageList(pageIndex, pageSize))
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
action.Invoke(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
totalNumber = count;
|
||||
}
|
||||
|
||||
public List<T> ToOffsetPage(int pageIndex, int pageSize)
|
||||
{
|
||||
if (this.Context.CurrentConnectionConfig.DbType != DbType.SqlServer)
|
||||
{
|
||||
this.QueryBuilder.Offset = "true";
|
||||
return this.ToPageList(pageIndex, pageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ToOffsetPage(pageIndex, pageSize);
|
||||
return this.ToList();
|
||||
}
|
||||
}
|
||||
public List<T> ToOffsetPage(int pageIndex, int pageSize, ref int totalNumber)
|
||||
{
|
||||
if (this.Context.CurrentConnectionConfig.DbType != DbType.SqlServer)
|
||||
{
|
||||
this.QueryBuilder.Offset = "true";
|
||||
return this.ToPageList(pageIndex, pageSize, ref totalNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalNumber = this.Clone().Count();
|
||||
_ToOffsetPage(pageIndex, pageSize);
|
||||
return this.Clone().ToList();
|
||||
}
|
||||
}
|
||||
public Task<List<T>> ToOffsetPageAsync(int pageIndex, int pageSize)
|
||||
{
|
||||
if (this.Context.CurrentConnectionConfig.DbType != DbType.SqlServer)
|
||||
{
|
||||
this.QueryBuilder.Offset = "true";
|
||||
return this.ToPageListAsync(pageIndex, pageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ToOffsetPage(pageIndex, pageSize);
|
||||
return this.ToListAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual List<T> ToPageList(int pageIndex, int pageSize)
|
||||
{
|
||||
pageIndex = _PageList(pageIndex, pageSize);
|
||||
return ToList();
|
||||
}
|
||||
public virtual List<TResult> ToPageList<TResult>(int pageIndex, int pageSize, ref int totalNumber, Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
if (this.QueryBuilder.Includes != null && this.QueryBuilder.Includes.Count > 0)
|
||||
{
|
||||
if (pageIndex == 0)
|
||||
pageIndex = 1;
|
||||
var list = this.Clone().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(expression);
|
||||
var countQueryable = this.Clone();
|
||||
countQueryable.QueryBuilder.Includes = null;
|
||||
totalNumber = countQueryable.Count();
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = this.Select(expression).ToPageList(pageIndex, pageSize, ref totalNumber).ToList();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
public virtual List<T> ToPageList(int pageIndex, int pageSize, ref int totalNumber)
|
||||
{
|
||||
var oldMapping = this.Context.MappingTables;
|
||||
var countQueryable = this.Clone();
|
||||
if (countQueryable.QueryBuilder.Offset == "true")
|
||||
{
|
||||
countQueryable.QueryBuilder.Offset = null;
|
||||
}
|
||||
totalNumber = countQueryable.Count();
|
||||
this.Context.MappingTables = oldMapping;
|
||||
return this.Clone().ToPageList(pageIndex, pageSize);
|
||||
}
|
||||
public virtual List<T> ToPageList(int pageIndex, int pageSize, ref int totalNumber, ref int totalPage)
|
||||
{
|
||||
var result = ToPageList(pageIndex, pageSize, ref totalNumber);
|
||||
totalPage = (totalNumber + pageSize - 1) / pageSize;
|
||||
return result;
|
||||
}
|
||||
public virtual string ToSqlString()
|
||||
{
|
||||
var sqlObj = this.Clone().ToSql();
|
||||
var result = sqlObj.Key;
|
||||
if (result == null) return null;
|
||||
result = UtilMethods.GetSqlString(this.Context.CurrentConnectionConfig, sqlObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public virtual KeyValuePair<string, List<SugarParameter>> ToSql()
|
||||
{
|
||||
if (!QueryBuilder.IsClone)
|
||||
{
|
||||
var newQueryable = this.Clone();
|
||||
newQueryable.QueryBuilder.IsClone = true;
|
||||
return newQueryable.ToSql();
|
||||
}
|
||||
else
|
||||
{
|
||||
return _ToSql();
|
||||
}
|
||||
}
|
||||
public string ToClassString(string className)
|
||||
{
|
||||
List<DbColumnInfo> columns = new List<DbColumnInfo>();
|
||||
var properties = typeof(T).GetProperties();
|
||||
foreach (var item in properties)
|
||||
{
|
||||
columns.Add(new DbColumnInfo()
|
||||
{
|
||||
DbColumnName = item.Name,
|
||||
PropertyName = UtilMethods.GetUnderType(item.PropertyType).Name,
|
||||
PropertyType = UtilMethods.GetUnderType(item.PropertyType)
|
||||
});
|
||||
}
|
||||
var result = ((this.Context.DbFirst) as DbFirstProvider).GetClassString(columns, ref className);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,542 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Reflection;
|
||||
using System.Dynamic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SqlSugar
|
||||
{
|
||||
|
||||
public partial class QueryableProvider<T> : QueryableAccessory, ISugarQueryable<T>
|
||||
{
|
||||
public async virtual Task<T[]> ToArrayAsync()
|
||||
{
|
||||
|
||||
var result = await this.ToListAsync();
|
||||
if (result.HasValue())
|
||||
return result.ToArray();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public virtual async Task<T> InSingleAsync(object pkValue)
|
||||
{
|
||||
Check.Exception(this.QueryBuilder.SelectValue.HasValue(), "'InSingle' and' Select' can't be used together,You can use .Select(it=>...).Single(it.id==1)");
|
||||
var list = await In(pkValue).ToListAsync();
|
||||
if (list == null) return default(T);
|
||||
else return list.SingleOrDefault();
|
||||
}
|
||||
public async Task<T> SingleAsync()
|
||||
{
|
||||
if (QueryBuilder.OrderByValue.IsNullOrEmpty())
|
||||
{
|
||||
QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate;
|
||||
}
|
||||
var oldSkip = QueryBuilder.Skip;
|
||||
var oldTake = QueryBuilder.Take;
|
||||
var oldOrderBy = QueryBuilder.OrderByValue;
|
||||
QueryBuilder.Skip = null;
|
||||
QueryBuilder.Take = null;
|
||||
QueryBuilder.OrderByValue = null;
|
||||
var result = await this.ToListAsync();
|
||||
QueryBuilder.Skip = oldSkip;
|
||||
QueryBuilder.Take = oldTake;
|
||||
QueryBuilder.OrderByValue = oldOrderBy;
|
||||
if (result == null || result.Count == 0)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
else if (result.Count == 2)
|
||||
{
|
||||
Check.Exception(true, ErrorMessage.GetThrowMessage(".Single() result must not exceed one . You can use.First()", "使用single查询结果集不能大于1,适合主键查询,如果大于1你可以使用Queryable.First"));
|
||||
return default(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
return result.SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<T> SingleAsync(Expression<Func<T, bool>> expression)
|
||||
{
|
||||
_Where(expression);
|
||||
var result = await SingleAsync();
|
||||
this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last());
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<T> FirstAsync()
|
||||
{
|
||||
if (QueryBuilder.OrderByValue.IsNullOrEmpty())
|
||||
{
|
||||
QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate;
|
||||
}
|
||||
if (QueryBuilder.Skip.HasValue)
|
||||
{
|
||||
QueryBuilder.Take = 1;
|
||||
var list = await this.ToListAsync();
|
||||
return list.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
QueryBuilder.Skip = 0;
|
||||
QueryBuilder.Take = 1;
|
||||
var result = await this.ToListAsync();
|
||||
if (result.HasValue())
|
||||
return result.FirstOrDefault();
|
||||
else
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<T> FirstAsync(Expression<Func<T, bool>> expression)
|
||||
{
|
||||
_Where(expression);
|
||||
var result = await FirstAsync();
|
||||
this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last());
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<bool> AnyAsync(Expression<Func<T, bool>> expression)
|
||||
{
|
||||
_Where(expression);
|
||||
var result = await AnyAsync();
|
||||
this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last());
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<bool> AnyAsync()
|
||||
{
|
||||
return await this.CountAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task<int> CountAsync()
|
||||
{
|
||||
if (this.QueryBuilder.Skip == null &&
|
||||
this.QueryBuilder.Take == null &&
|
||||
this.QueryBuilder.OrderByValue == null &&
|
||||
this.QueryBuilder.PartitionByValue == null &&
|
||||
this.QueryBuilder.SelectValue == null &&
|
||||
this.QueryBuilder.Includes == null &&
|
||||
this.QueryBuilder.IsDistinct == false)
|
||||
{
|
||||
var list = await this.Clone().Select<int>(" COUNT(1) ").ToListAsync();
|
||||
return list.FirstOrDefault();
|
||||
}
|
||||
MappingTableList expMapping;
|
||||
int result;
|
||||
_CountBegin(out expMapping, out result);
|
||||
if (IsCache)
|
||||
{
|
||||
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
|
||||
result = CacheSchemeMain.GetOrCreate<int>(cacheService, this.QueryBuilder, () => { return GetCount(); }, CacheTime, this.Context, CacheKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await GetCountAsync();
|
||||
}
|
||||
_CountEnd(expMapping);
|
||||
return result;
|
||||
}
|
||||
public async Task<int> CountAsync(Expression<Func<T, bool>> expression)
|
||||
{
|
||||
_Where(expression);
|
||||
var result = await CountAsync();
|
||||
this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last());
|
||||
return result;
|
||||
}
|
||||
public async Task<TResult> MaxAsync<TResult>(string maxField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.MaxTemplate, maxField));
|
||||
var list = await this._ToListAsync<TResult>();
|
||||
var result = list.SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Task<TResult> MaxAsync<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _MaxAsync<TResult>(expression);
|
||||
}
|
||||
|
||||
public async Task<TResult> MinAsync<TResult>(string minField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.MinTemplate, minField));
|
||||
var list = await this._ToListAsync<TResult>();
|
||||
var result = list.SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Task<TResult> MinAsync<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _MinAsync<TResult>(expression);
|
||||
}
|
||||
|
||||
public async Task<TResult> SumAsync<TResult>(string sumField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.SumTemplate, sumField));
|
||||
var list = await this._ToListAsync<TResult>();
|
||||
var result = list.SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Task<TResult> SumAsync<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _SumAsync<TResult>(expression);
|
||||
}
|
||||
|
||||
public async Task<TResult> AvgAsync<TResult>(string avgField)
|
||||
{
|
||||
this.Select(string.Format(QueryBuilder.AvgTemplate, avgField));
|
||||
var list = await this._ToListAsync<TResult>();
|
||||
var result = list.SingleOrDefault();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Task<TResult> AvgAsync<TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return _AvgAsync<TResult>(expression);
|
||||
}
|
||||
|
||||
public Task<List<T>> ToListAsync()
|
||||
{
|
||||
InitMapping();
|
||||
return _ToListAsync<T>();
|
||||
}
|
||||
public Task<List<T>> ToPageListAsync(int pageIndex, int pageSize)
|
||||
{
|
||||
pageIndex = _PageList(pageIndex, pageSize);
|
||||
return ToListAsync();
|
||||
}
|
||||
public async virtual Task<List<TResult>> ToPageListAsync<TResult>(int pageIndex, int pageSize, RefAsync<int> totalNumber, Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
if (this.QueryBuilder.Includes != null && this.QueryBuilder.Includes.Count > 0)
|
||||
{
|
||||
if (pageIndex == 0)
|
||||
pageIndex = 1;
|
||||
var list = await this.Clone().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(expression);
|
||||
var countQueryable = this.Clone();
|
||||
countQueryable.QueryBuilder.Includes = null;
|
||||
totalNumber.Value = await countQueryable.CountAsync();
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = await this.Select(expression).ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
public async Task<List<T>> ToPageListAsync(int pageIndex, int pageSize, RefAsync<int> totalNumber)
|
||||
{
|
||||
var oldMapping = this.Context.MappingTables;
|
||||
var countQueryable = this.Clone();
|
||||
if (countQueryable.QueryBuilder.Offset == "true")
|
||||
{
|
||||
countQueryable.QueryBuilder.Offset = null;
|
||||
}
|
||||
totalNumber.Value = await countQueryable.CountAsync();
|
||||
this.Context.MappingTables = oldMapping;
|
||||
return await this.Clone().ToPageListAsync(pageIndex, pageSize);
|
||||
}
|
||||
public async Task<List<T>> ToPageListAsync(int pageNumber, int pageSize, RefAsync<int> totalNumber, RefAsync<int> totalPage)
|
||||
{
|
||||
var result = await ToPageListAsync(pageNumber, pageSize, totalNumber);
|
||||
totalPage.Value = (totalNumber.Value + pageSize - 1) / pageSize;
|
||||
return result;
|
||||
}
|
||||
public async Task<string> ToJsonAsync()
|
||||
{
|
||||
if (IsCache)
|
||||
{
|
||||
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
|
||||
var result = CacheSchemeMain.GetOrCreate<string>(cacheService, this.QueryBuilder, () =>
|
||||
{
|
||||
return this.Context.Utilities.SerializeObject(this.ToList(), typeof(T));
|
||||
}, CacheTime, this.Context, CacheKey);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.Context.Utilities.SerializeObject(await this.ToListAsync(), typeof(T));
|
||||
}
|
||||
}
|
||||
public async Task<string> ToJsonPageAsync(int pageIndex, int pageSize)
|
||||
{
|
||||
return this.Context.Utilities.SerializeObject(await this.ToPageListAsync(pageIndex, pageSize), typeof(T));
|
||||
}
|
||||
public async Task<string> ToJsonPageAsync(int pageIndex, int pageSize, RefAsync<int> totalNumber)
|
||||
{
|
||||
var oldMapping = this.Context.MappingTables;
|
||||
totalNumber.Value = await this.Clone().CountAsync();
|
||||
this.Context.MappingTables = oldMapping;
|
||||
return await this.Clone().ToJsonPageAsync(pageIndex, pageSize);
|
||||
}
|
||||
public async Task<DataTable> ToDataTableAsync()
|
||||
{
|
||||
QueryBuilder.ResultType = typeof(SugarCacheDataTable);
|
||||
InitMapping();
|
||||
var sqlObj = this._ToSql();
|
||||
RestoreMapping();
|
||||
DataTable result = null;
|
||||
if (IsCache)
|
||||
{
|
||||
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
|
||||
result = CacheSchemeMain.GetOrCreate<DataTable>(cacheService, this.QueryBuilder, () => { return this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); }, CacheTime, this.Context, CacheKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await this.Db.GetDataTableAsync(sqlObj.Key, sqlObj.Value.ToArray());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public Task<DataTable> ToDataTablePageAsync(int pageIndex, int pageSize)
|
||||
{
|
||||
pageIndex = _PageList(pageIndex, pageSize);
|
||||
return ToDataTableAsync();
|
||||
}
|
||||
public async Task<DataTable> ToDataTablePageAsync(int pageIndex, int pageSize, RefAsync<int> totalNumber)
|
||||
{
|
||||
var oldMapping = this.Context.MappingTables;
|
||||
totalNumber.Value = await this.Clone().CountAsync();
|
||||
this.Context.MappingTables = oldMapping;
|
||||
return await this.Clone().ToDataTablePageAsync(pageIndex, pageSize);
|
||||
}
|
||||
public async Task<List<T>> ToOffsetPageAsync(int pageIndex, int pageSize, RefAsync<int> totalNumber)
|
||||
{
|
||||
if (this.Context.CurrentConnectionConfig.DbType != DbType.SqlServer)
|
||||
{
|
||||
this.QueryBuilder.Offset = "true";
|
||||
return await this.ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalNumber.Value = await this.Clone().CountAsync();
|
||||
_ToOffsetPage(pageIndex, pageSize);
|
||||
return await this.Clone().ToListAsync();
|
||||
}
|
||||
}
|
||||
public virtual async Task ForEachAsync(Action<T> action, int singleMaxReads = 300, System.Threading.CancellationTokenSource cancellationTokenSource = null)
|
||||
{
|
||||
Check.Exception(this.QueryBuilder.Skip > 0 || this.QueryBuilder.Take > 0, ErrorMessage.GetThrowMessage("no support Skip take, use PageForEach", "不支持Skip Take,请使用 Queryale.PageForEach"));
|
||||
RefAsync<int> totalNumber = 0;
|
||||
RefAsync<int> totalPage = 1;
|
||||
for (int i = 1; i <= totalPage; i++)
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
var queryable = this.Clone();
|
||||
var page =
|
||||
totalPage == 1 ?
|
||||
await queryable.ToPageListAsync(i, singleMaxReads, totalNumber, totalPage) :
|
||||
await queryable.ToPageListAsync(i, singleMaxReads);
|
||||
foreach (var item in page)
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
action.Invoke(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
public virtual async Task ForEachByPageAsync(Action<T> action, int pageIndex, int pageSize, RefAsync<int> totalNumber, int singleMaxReads = 300, System.Threading.CancellationTokenSource cancellationTokenSource = null)
|
||||
{
|
||||
int count = this.Clone().Count();
|
||||
if (count > 0)
|
||||
{
|
||||
if (pageSize > singleMaxReads && count - ((pageIndex - 1) * pageSize) > singleMaxReads)
|
||||
{
|
||||
Int32 Skip = (pageIndex - 1) * pageSize;
|
||||
Int32 NowCount = count - Skip;
|
||||
Int32 number = 0;
|
||||
if (NowCount > pageSize) NowCount = pageSize;
|
||||
while (NowCount > 0)
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
if (number + singleMaxReads > pageSize) singleMaxReads = NowCount;
|
||||
foreach (var item in await this.Clone().Skip(Skip).Take(singleMaxReads).ToListAsync())
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
action.Invoke(item);
|
||||
}
|
||||
NowCount -= singleMaxReads;
|
||||
Skip += singleMaxReads;
|
||||
number += singleMaxReads;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
foreach (var item in this.Clone().ToPageList(pageIndex, pageSize))
|
||||
{
|
||||
if (cancellationTokenSource?.IsCancellationRequested == true) return;
|
||||
action.Invoke(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
totalNumber = count;
|
||||
}
|
||||
public async Task<List<T>> SetContextAsync<ParameterT>(Expression<Func<T, object>> thisFiled1, Expression<Func<object>> mappingFiled1,
|
||||
Expression<Func<T, object>> thisFiled2, Expression<Func<object>> mappingFiled2,
|
||||
ParameterT parameter)
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return new List<T>();
|
||||
}
|
||||
var rightEntity = this.Context.EntityMaintenance.GetEntityInfo<ParameterT>();
|
||||
var leftEntity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
List<T> result = new List<T>();
|
||||
var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext<ParameterT>;
|
||||
var list = queryableContext.list;
|
||||
var key = thisFiled1.ToString() + mappingFiled1.ToString() +
|
||||
thisFiled2.ToString() + mappingFiled2.ToString() +
|
||||
typeof(ParameterT).FullName + typeof(T).FullName;
|
||||
MappingFieldsHelper<ParameterT> fieldsHelper = new MappingFieldsHelper<ParameterT>();
|
||||
var mappings = new List<MappingFieldsExpression>() {
|
||||
new MappingFieldsExpression(){
|
||||
LeftColumnExpression=thisFiled1,
|
||||
LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled1)),
|
||||
RightColumnExpression=mappingFiled1,
|
||||
RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled1))
|
||||
},
|
||||
new MappingFieldsExpression(){
|
||||
LeftColumnExpression=thisFiled2,
|
||||
LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled2)),
|
||||
RightColumnExpression=mappingFiled2,
|
||||
RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled2))
|
||||
}
|
||||
};
|
||||
var conditionals = fieldsHelper.GetMppingSql(list.Cast<object>().ToList(), mappings);
|
||||
if (queryableContext.TempChildLists == null)
|
||||
queryableContext.TempChildLists = new Dictionary<string, object>();
|
||||
if (list != null && queryableContext.TempChildLists.ContainsKey(key))
|
||||
{
|
||||
result = (List<T>)queryableContext.TempChildLists[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await this.Clone().Where(conditionals, true).ToListAsync();
|
||||
queryableContext.TempChildLists[key] = result;
|
||||
}
|
||||
List<object> listObj = result.Select(it => (object)it).ToList();
|
||||
object obj = (object)parameter;
|
||||
var newResult = fieldsHelper.GetSetList(obj, listObj, mappings).Select(it => (T)it).ToList();
|
||||
return newResult;
|
||||
}
|
||||
|
||||
public async Task<List<T>> SetContextAsync<ParameterT>(Expression<Func<T, object>> thisFiled, Expression<Func<object>> mappingFiled, ParameterT parameter)
|
||||
{
|
||||
List<T> result = new List<T>();
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<ParameterT>();
|
||||
var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext<ParameterT>;
|
||||
var list = queryableContext.list;
|
||||
var pkName = "";
|
||||
if ((mappingFiled as LambdaExpression).Body is UnaryExpression)
|
||||
{
|
||||
pkName = (((mappingFiled as LambdaExpression).Body as UnaryExpression).Operand as MemberExpression).Member.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkName = ((mappingFiled as LambdaExpression).Body as MemberExpression).Member.Name;
|
||||
}
|
||||
var key = thisFiled.ToString() + mappingFiled.ToString() + typeof(ParameterT).FullName + typeof(T).FullName;
|
||||
var ids = list.Select(it => it.GetType().GetProperty(pkName).GetValue(it)).ToArray();
|
||||
if (queryableContext.TempChildLists == null)
|
||||
queryableContext.TempChildLists = new Dictionary<string, object>();
|
||||
if (list != null && queryableContext.TempChildLists.ContainsKey(key))
|
||||
{
|
||||
result = (List<T>)queryableContext.TempChildLists[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (queryableContext.TempChildLists == null)
|
||||
queryableContext.TempChildLists = new Dictionary<string, object>();
|
||||
await this.Context.Utilities.PageEachAsync(ids, 200, async pageIds =>
|
||||
{
|
||||
result.AddRange(await this.Clone().In(thisFiled, pageIds).ToListAsync());
|
||||
});
|
||||
queryableContext.TempChildLists[key] = result;
|
||||
}
|
||||
var name = "";
|
||||
if ((thisFiled as LambdaExpression).Body is UnaryExpression)
|
||||
{
|
||||
name = (((thisFiled as LambdaExpression).Body as UnaryExpression).Operand as MemberExpression).Member.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = ((thisFiled as LambdaExpression).Body as MemberExpression).Member.Name;
|
||||
}
|
||||
var pkValue = parameter.GetType().GetProperty(pkName).GetValue(parameter);
|
||||
result = result.Where(it => it.GetType().GetProperty(name).GetValue(it).ObjToString() == pkValue.ObjToString()).ToList();
|
||||
return result;
|
||||
}
|
||||
public async Task<Dictionary<string, object>> ToDictionaryAsync(Expression<Func<T, object>> key, Expression<Func<T, object>> value)
|
||||
{
|
||||
this.QueryBuilder.ResultType = typeof(SugarCacheDictionary);
|
||||
var keyName = QueryBuilder.GetExpressionValue(key, ResolveExpressType.FieldSingle).GetResultString();
|
||||
var valueName = QueryBuilder.GetExpressionValue(value, ResolveExpressType.FieldSingle).GetResultString();
|
||||
var list = await this.Select<KeyValuePair<string, object>>(keyName + "," + valueName).ToListAsync();
|
||||
var result = list.ToDictionary(it => it.Key.ObjToString(), it => it.Value);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<T>> ToTreeAsync(Expression<Func<T, IEnumerable<object>>> childListExpression, Expression<Func<T, object>> parentIdExpression, object rootValue)
|
||||
{
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var pk = GetTreeKey(entity); ;
|
||||
var list = await this.ToListAsync();
|
||||
return GetTreeRoot(childListExpression, parentIdExpression, pk, list, rootValue);
|
||||
}
|
||||
|
||||
public async Task<List<T>> ToParentListAsync(Expression<Func<T, object>> parentIdExpression, object primaryKeyValue)
|
||||
{
|
||||
List<T> result = new List<T>() { };
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var isTreeKey = entity.Columns.Any(it => it.IsTreeKey);
|
||||
if (isTreeKey)
|
||||
{
|
||||
return await _ToParentListByTreeKeyAsync(parentIdExpression, primaryKeyValue);
|
||||
}
|
||||
Check.Exception(entity.Columns.Where(it => it.IsPrimarykey).Count() == 0, "No Primary key");
|
||||
var parentIdName = UtilConvert.ToMemberExpression((parentIdExpression as LambdaExpression).Body).Member.Name;
|
||||
var ParentInfo = entity.Columns.First(it => it.PropertyName == parentIdName);
|
||||
var parentPropertyName = ParentInfo.DbColumnName;
|
||||
var tableName = this.QueryBuilder.GetTableNameString;
|
||||
if (this.QueryBuilder.IsSingle() == false)
|
||||
{
|
||||
if (this.QueryBuilder.JoinQueryInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
if (this.QueryBuilder.EasyJoinInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
}
|
||||
var current = await this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).InSingleAsync(primaryKeyValue);
|
||||
if (current != null)
|
||||
{
|
||||
result.Add(current);
|
||||
object parentId = ParentInfo.PropertyInfo.GetValue(current, null);
|
||||
int i = 0;
|
||||
while (parentId != null && await this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).In(parentId).AnyAsync())
|
||||
{
|
||||
Check.Exception(i > 100, ErrorMessage.GetThrowMessage("Dead cycle", "出现死循环或超出循环上限(100),检查最顶层的ParentId是否是null或者0"));
|
||||
var parent = await this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).InSingleAsync(parentId);
|
||||
result.Add(parent);
|
||||
parentId = ParentInfo.PropertyInfo.GetValue(parent, null);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public async Task<List<T>> ToChildListAsync(Expression<Func<T, object>> parentIdExpression, object primaryKeyValue, bool isContainOneself = true)
|
||||
{
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var pk = GetTreeKey(entity);
|
||||
var list = await this.ToListAsync();
|
||||
return GetChildList(parentIdExpression, pk, list, primaryKeyValue, isContainOneself);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,125 @@ namespace SqlSugar
|
||||
{
|
||||
public partial class QueryableProvider<T> : QueryableAccessory, ISugarQueryable<T>
|
||||
{
|
||||
#region Private Methods
|
||||
|
||||
private List<T> _ToParentListByTreeKey(Expression<Func<T, object>> parentIdExpression, object primaryKeyValue)
|
||||
{
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var treeKey = entity.Columns.FirstOrDefault(it => it.IsTreeKey);
|
||||
List<T> result = new List<T>() { };
|
||||
var parentIdName = UtilConvert.ToMemberExpression((parentIdExpression as LambdaExpression).Body).Member.Name;
|
||||
var ParentInfo = entity.Columns.First(it => it.PropertyName == parentIdName);
|
||||
var parentPropertyName = ParentInfo.DbColumnName;
|
||||
var tableName = this.QueryBuilder.GetTableNameString;
|
||||
if (this.QueryBuilder.IsSingle() == false)
|
||||
{
|
||||
if (this.QueryBuilder.JoinQueryInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
if (this.QueryBuilder.EasyJoinInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
}
|
||||
var current = this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).Where(new List<IConditionalModel>() {
|
||||
new ConditionalModel()
|
||||
{
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
CSharpTypeName = treeKey.PropertyInfo.PropertyType.Name,
|
||||
FieldValue = primaryKeyValue + "",
|
||||
FieldName = treeKey.DbColumnName
|
||||
} }).First();
|
||||
if (current != null)
|
||||
{
|
||||
result.Add(current);
|
||||
object parentId = ParentInfo.PropertyInfo.GetValue(current, null);
|
||||
int i = 0;
|
||||
while (parentId != null && this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).Where(new List<IConditionalModel>() {
|
||||
new ConditionalModel()
|
||||
{
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
CSharpTypeName = treeKey.PropertyInfo.PropertyType.Name,
|
||||
FieldValue = parentId + "",
|
||||
FieldName = treeKey.DbColumnName
|
||||
} }).Any())
|
||||
{
|
||||
Check.Exception(i > 100, ErrorMessage.GetThrowMessage("Dead cycle", "出现死循环或超出循环上限(100),检查最顶层的ParentId是否是null或者0"));
|
||||
var parent = this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).Where(new List<IConditionalModel>() {
|
||||
new ConditionalModel()
|
||||
{
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
CSharpTypeName = treeKey.PropertyInfo.PropertyType.Name,
|
||||
FieldValue = parentId + "",
|
||||
FieldName = treeKey.DbColumnName
|
||||
} }).First();
|
||||
result.Add(parent);
|
||||
parentId = ParentInfo.PropertyInfo.GetValue(parent, null);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<List<T>> _ToParentListByTreeKeyAsync(Expression<Func<T, object>> parentIdExpression, object primaryKeyValue)
|
||||
{
|
||||
var entity = this.Context.EntityMaintenance.GetEntityInfo<T>();
|
||||
var treeKey = entity.Columns.FirstOrDefault(it => it.IsTreeKey);
|
||||
List<T> result = new List<T>() { };
|
||||
var parentIdName = UtilConvert.ToMemberExpression((parentIdExpression as LambdaExpression).Body).Member.Name;
|
||||
var ParentInfo = entity.Columns.First(it => it.PropertyName == parentIdName);
|
||||
var parentPropertyName = ParentInfo.DbColumnName;
|
||||
var tableName = this.QueryBuilder.GetTableNameString;
|
||||
if (this.QueryBuilder.IsSingle() == false)
|
||||
{
|
||||
if (this.QueryBuilder.JoinQueryInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
if (this.QueryBuilder.EasyJoinInfos.Count > 0)
|
||||
{
|
||||
tableName = this.QueryBuilder.JoinQueryInfos.First().TableName;
|
||||
}
|
||||
}
|
||||
var current = await this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).Where(new List<IConditionalModel>() {
|
||||
new ConditionalModel()
|
||||
{
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
CSharpTypeName = treeKey.PropertyInfo.PropertyType.Name,
|
||||
FieldValue = primaryKeyValue + "",
|
||||
FieldName = treeKey.DbColumnName
|
||||
} }).FirstAsync();
|
||||
if (current != null)
|
||||
{
|
||||
result.Add(current);
|
||||
object parentId = ParentInfo.PropertyInfo.GetValue(current, null);
|
||||
int i = 0;
|
||||
while (parentId != null && await this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).Where(new List<IConditionalModel>() {
|
||||
new ConditionalModel()
|
||||
{
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
CSharpTypeName = treeKey.PropertyInfo.PropertyType.Name,
|
||||
FieldValue = parentId + "",
|
||||
FieldName = treeKey.DbColumnName
|
||||
} }).AnyAsync())
|
||||
{
|
||||
Check.Exception(i > 100, ErrorMessage.GetThrowMessage("Dead cycle", "出现死循环或超出循环上限(100),检查最顶层的ParentId是否是null或者0"));
|
||||
var parent = await this.Context.Queryable<T>().AS(tableName).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).Where(new List<IConditionalModel>() {
|
||||
new ConditionalModel()
|
||||
{
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
CSharpTypeName = treeKey.PropertyInfo.PropertyType.Name,
|
||||
FieldValue = parentId + "",
|
||||
FieldName = treeKey.DbColumnName
|
||||
} }).FirstAsync();
|
||||
result.Add(parent);
|
||||
parentId = ParentInfo.PropertyInfo.GetValue(parent, null);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual KeyValuePair<string, List<SugarParameter>> _ToSql()
|
||||
{
|
||||
InitMapping();
|
||||
@@ -1193,7 +1311,5 @@ namespace SqlSugar
|
||||
|
||||
return cacheDurationInSeconds;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -114,6 +114,8 @@
|
||||
<Compile Include="Abstract\FastestProvider\SplitFastest.cs" />
|
||||
<Compile Include="Abstract\FilterProvider\FilterProvider.cs" />
|
||||
<Compile Include="Abstract\InsertableProvider\InsertableHelper.cs" />
|
||||
<Compile Include="Abstract\QueryableProvider\QueryableExecuteSqlAsync.cs" />
|
||||
<Compile Include="Abstract\QueryableProvider\QueryableExecuteSql.cs" />
|
||||
<Compile Include="Abstract\QueryableProvider\QueryableProperties.cs" />
|
||||
<Compile Include="Abstract\QueryableProvider\QueryableProvider11-12.cs" />
|
||||
<Compile Include="Abstract\QueryableProvider\QueryableProvider06-10.cs" />
|
||||
|
||||
Reference in New Issue
Block a user