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; using Newtonsoft.Json.Serialization; namespace SqlSugar { public partial class QueryableProvider : QueryableAccessory, ISugarQueryable { public virtual T Single() { 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 = this.ToList(); 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 virtual T Single(Expression> expression) { _Where(expression); var result = Single(); this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); return result; } public virtual T First() { if (QueryBuilder.OrderByValue.IsNullOrEmpty()) { QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate; } if (QueryBuilder.Skip.HasValue) { QueryBuilder.Take = 1; return this.ToList().FirstOrDefault(); } else { QueryBuilder.Skip = 0; QueryBuilder.Take = 1; var result = this.ToList(); if (result.HasValue()) return result.FirstOrDefault(); else return default(T); } } public virtual T First(Expression> expression) { _Where(expression); var result = First(); this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); return result; } public virtual bool Any(Expression> expression) { _Where(expression); var result = Any(); this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); return result; } public virtual bool Any() { return this.Clone().Take(1).Select("1").ToList().Count() > 0; } public virtual List ToList(Expression> expression) { if (this.QueryBuilder.Includes != null && this.QueryBuilder.Includes.Count > 0) { return NavSelectHelper.GetList(expression, this); // var list = this.ToList().Select(expression.Compile()).ToList(); // return list; } else { var list = this.Select(expression).ToList(); return list; } } 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) { if (StaticConfig.EnableAot) { var sqlobj = this.Clone().Select(" COUNT(1) ").ToSql(); return this.Context.Ado.GetInt(sqlobj.Key,sqlobj.Value); } return this.Clone().Select(" 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(cacheService, this.QueryBuilder, () => { return GetCount(); }, CacheTime, this.Context, CacheKey); } else { result = GetCount(); } _CountEnd(expMapping); return result; } public virtual int Count(Expression> expression) { _Where(expression); var result = Count(); this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); return result; } public virtual TResult Max(string maxField) { this.Select(string.Format(QueryBuilder.MaxTemplate, maxField)); var result = this._ToList().SingleOrDefault(); return result; } public virtual TResult Max(Expression> expression) { return _Max(expression); } public virtual TResult Min(string minField) { this.Select(string.Format(QueryBuilder.MinTemplate, minField)); var result = this._ToList().SingleOrDefault(); return result; } public virtual TResult Min(Expression> expression) { return _Min(expression); } public virtual TResult Sum(string sumField) { this.Select(string.Format(QueryBuilder.SumTemplate, sumField)); var result = this._ToList().SingleOrDefault(); return result; } public virtual TResult Sum(Expression> expression) { return _Sum(expression); } public virtual TResult Avg(string avgField) { this.Select(string.Format(QueryBuilder.AvgTemplate, avgField)); var result = this._ToList().SingleOrDefault(); return result; } public virtual TResult Avg(Expression> expression) { return _Avg(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(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)); } #region 内存行转列 #region 同步 public virtual DataTable ToPivotTable(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { return this.ToList().ToPivotTable(columnSelector, rowSelector, dataSelector); } public virtual List ToPivotList(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { return ToPivotEnumerable(columnSelector, rowSelector, dataSelector).ToList(); } public virtual IEnumerable ToPivotEnumerable(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { return this.ToList().ToPivotList(columnSelector, rowSelector, dataSelector); } public virtual string ToPivotJson(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { var list = ToPivotEnumerable(columnSelector, rowSelector, dataSelector).ToList(); return this.Context.Utilities.SerializeObject(list); } #endregion #region 异步 public virtual async Task ToPivotTableAsync(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { return (await this.ToListAsync()).ToPivotTable(columnSelector, rowSelector, dataSelector); } public virtual async Task> ToPivotListAsync(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { return (await ToPivotEnumerableAsync(columnSelector, rowSelector, dataSelector)).ToList(); } public virtual async Task> ToPivotEnumerableAsync(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { return (await this.ToListAsync()).ToPivotList(columnSelector, rowSelector, dataSelector); } public virtual async Task ToPivotJsonAsync(Func columnSelector, Expression> rowSelector, Func, TData> dataSelector) { var list = (await ToPivotEnumerableAsync(columnSelector, rowSelector, dataSelector)).ToList(); return this.Context.Utilities.SerializeObject(list); } #endregion #endregion public List ToChildList(Expression> parentIdExpression, object primaryKeyValue, bool isContainOneself = true) { var entity = this.Context.EntityMaintenance.GetEntityInfo(); var pk = GetTreeKey(entity); var list = this.ToList(); return GetChildList(parentIdExpression, pk, list, primaryKeyValue, isContainOneself); } public List ToChildList(Expression> parentIdExpression, object [] primaryKeyValues, bool isContainOneself = true) { var entity = this.Context.EntityMaintenance.GetEntityInfo(); var pk = GetTreeKey(entity); var list = this.ToList(); List result = new List(); foreach (var item in primaryKeyValues) { result.AddRange(GetChildList(parentIdExpression, pk, list, item, isContainOneself)); } return result; } public List ToParentList(Expression> parentIdExpression, object primaryKeyValue) { var entity = this.Context.EntityMaintenance.GetEntityInfo(); var isTreeKey = entity.Columns.Any(it => it.IsTreeKey); if (isTreeKey) { return _ToParentListByTreeKey(parentIdExpression, primaryKeyValue); } List result = new List() { }; 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().AS(tableName).WithCacheIF(this.IsCache,this.CacheTime).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).ClearFilter(this.QueryBuilder.RemoveFilters).InSingle(primaryKeyValue); if (current != null) { result.Add(current); object parentId = ParentInfo.PropertyInfo.GetValue(current, null); int i = 0; while (parentId != null && this.Context.Queryable().AS(tableName).WithCacheIF(this.IsCache, this.CacheTime).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).ClearFilter(this.QueryBuilder.RemoveFilters).In(parentId).Any()) { Check.Exception(i > 200, ErrorMessage.GetThrowMessage("Dead cycle", "出现死循环或超出循环上限(200),检查最顶层的ParentId是否是null或者0")); var parent = this.Context.Queryable().AS(tableName).WithCacheIF(this.IsCache, this.CacheTime).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).InSingle(parentId); result.Add(parent); parentId = ParentInfo.PropertyInfo.GetValue(parent, null); ++i; } } return result; } public List ToParentList(Expression> parentIdExpression, object primaryKeyValue, Expression> parentWhereExpression) { var entity = this.Context.EntityMaintenance.GetEntityInfo(); var isTreeKey = entity.Columns.Any(it => it.IsTreeKey); if (isTreeKey) { return _ToParentListByTreeKey(parentIdExpression, primaryKeyValue,parentWhereExpression); } List result = new List() { }; 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().AS(tableName).WhereIF(parentWhereExpression!=default, parentWhereExpression).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().AS(tableName).WhereIF(parentWhereExpression!=default, parentWhereExpression).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).In(parentId).Any()) { Check.Exception(i > 200, ErrorMessage.GetThrowMessage("Dead cycle", "出现死循环或超出循环上限(200),检查最顶层的ParentId是否是null或者0")); var parent = this.Context.Queryable().AS(tableName).WhereIF(parentWhereExpression!=default, parentWhereExpression).Filter(null, this.QueryBuilder.IsDisabledGobalFilter).InSingle(parentId); result.Add(parent); parentId = ParentInfo.PropertyInfo.GetValue(parent, null); ++i; } } return result; } public List ToTree(string childPropertyName, string parentIdPropertyName, object rootValue, string primaryKeyPropertyName) { var entity = this.Context.EntityMaintenance.GetEntityInfo(); var pk = primaryKeyPropertyName; var list = this.ToList(); Expression >> childListExpression = (Expression>>)ExpressionBuilderHelper.CreateExpressionSelectField(typeof(T),childPropertyName,typeof(IEnumerable)); Expression> parentIdExpression = (Expression>)ExpressionBuilderHelper.CreateExpressionSelectFieldObject(typeof(T), parentIdPropertyName); return GetTreeRoot(childListExpression, parentIdExpression, pk, list, rootValue) ?? new List(); } public List ToTree(Expression>> childListExpression, Expression> parentIdExpression, object rootValue, Expression> primaryKeyExpression) { var entity = this.Context.EntityMaintenance.GetEntityInfo(); var pk = ExpressionTool.GetMemberName(primaryKeyExpression); var list = this.ToList(); return GetTreeRoot(childListExpression, parentIdExpression, pk, list, rootValue) ?? new List(); } public List ToTree(Expression>> childListExpression, Expression> parentIdExpression, object rootValue) { var entity = this.Context.EntityMaintenance.GetEntityInfo(); var pk = GetTreeKey(entity); var list = this.ToList(); return GetTreeRoot(childListExpression, parentIdExpression, pk, list, rootValue)??new List(); } public List ToTree(Expression>> childListExpression, Expression> parentIdExpression, object rootValue, object[] childIds) { var list = this.ToList(); return TreeAndFilterIds(childListExpression, parentIdExpression, rootValue, childIds, ref list) ?? new List(); } public List ToTree(Expression>> childListExpression, Expression> parentIdExpression, object rootValue, object[] childIds, Expression> primaryKeyExpression) { var list = this.ToList(); return TreeAndFilterIds(childListExpression, parentIdExpression,primaryKeyExpression, rootValue, childIds, ref list) ?? new List(); } public virtual DataTable ToDataTableByEntity() { var list = this.ToList(); return this.Context.Utilities.ListToDataTable(list); } 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(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 DataTable ToDataTableByEntityPage(int pageNumber, int pageSize, ref int totalNumber) { var list=this.ToPageList(pageNumber, pageSize,ref totalNumber); return this.Context.Utilities.ListToDataTable(list); } 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 ToDictionary(Expression> key, Expression> value) { return this.ToDictionary(key, value).ToDictionary(it => it.Key, it => (ValueType)UtilMethods.ChangeType2(it.Value, typeof(ValueType))); } public Dictionary ToDictionary(Expression> key, Expression> value) { if (this.QueryBuilder.IsSingle() == false && (this.QueryBuilder.AsTables == null||this.QueryBuilder.AsTables.Count==0)) { return this.MergeTable().ToDictionary(key,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 isJson=this.Context.EntityMaintenance.GetEntityInfo().Columns.Where(it => it.IsJson && it.PropertyName == ExpressionTool.GetMemberName(value)).Any(); if (isJson) { var result = this.Select(keyName + "," + valueName).ToList().ToDictionary(ExpressionTool.GetMemberName(key), ExpressionTool.GetMemberName(value)); return result; } else if (valueName == null) { // 编译key和value的表达式树为委托 var keySelector = key.Compile(); var valueSelector = value.Compile(); Dictionary objDic= this.ToList().ToDictionary(keySelector, valueSelector); return objDic.ToDictionary(it=>it.Key?.ToString(),it=>it.Value); } else { var result = this.Select>(keyName + "," + valueName).ToList().ToDictionary(it => it.Key.ObjToString(), it => it.Value); return result; } } public List> ToDictionaryList() { var list = this.ToList(); if (list == null) return null; else return this.Context.Utilities.DeserializeObject>>(this.Context.Utilities.SerializeObject(list)); } public async Task>> ToDictionaryListAsync() { var list = await this.ToListAsync(); if (list == null) return null; else return this.Context.Utilities.DeserializeObject>>(this.Context.Utilities.SerializeObject(list)); } public virtual List ToList() { InitMapping(); return _ToList(); } public List SetContext(Expression> whereExpression, ParameterT parameter) { var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext; var rootList = queryableContext.list; List> queryableList = new List>(); var index = rootList.IndexOf(parameter); var selector = this.Clone().QueryBuilder.GetSelectValue+$",{index} as "; var sqlObj=this.Clone().Where(whereExpression).Select(selector+"") .Select(it => (object) new { it, sql_sugar_index = index }); queryableList.Add(sqlObj); var allList = this.Context.Union(queryableList) .Select(it=>new { it=default(T), sql_sugar_index =0}) .Select("*").ToList(); var result = new List(); throw new Exception("开发中"); } public List SetContext(Expression> thisFiled, Expression> mappingFiled, ParameterT parameter) { if (parameter == null) { return new List(); } List result = new List(); var entity = this.Context.EntityMaintenance.GetEntityInfo(); var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext; 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(); if (list != null && queryableContext.TempChildLists.ContainsKey(key)) { result = (List)queryableContext.TempChildLists[key]; } else { if (queryableContext.TempChildLists == null) queryableContext.TempChildLists = new Dictionary(); 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 SetContext(Expression> thisFiled1, Expression> mappingFiled1, Expression> thisFiled2, Expression> mappingFiled2, ParameterT parameter) { if (parameter == null) { return new List(); } var rightEntity = this.Context.EntityMaintenance.GetEntityInfo(); var leftEntity = this.Context.EntityMaintenance.GetEntityInfo(); List result = new List(); var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext; var list = queryableContext.list; var key = thisFiled1.ToString() + mappingFiled1.ToString() + thisFiled2.ToString() + mappingFiled2.ToString() + typeof(ParameterT).FullName + typeof(T).FullName; MappingFieldsHelper fieldsHelper = new MappingFieldsHelper(); var mappings = new List() { 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().ToList(), mappings); if (queryableContext.TempChildLists == null) queryableContext.TempChildLists = new Dictionary(); if (list != null && queryableContext.TempChildLists.ContainsKey(key)) { result = (List)queryableContext.TempChildLists[key]; } else { result = this.Clone().Where(conditionals, true).ToList(); queryableContext.TempChildLists[key] = result; } List 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 void ForEachDataReader(Action action) { var queryable = this.Clone(); var sql = queryable.ToSql(); var dr = this.Context.Ado.GetDataReader(sql.Key,sql.Value); var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(); var columns = UtilMethods.GetColumnInfo(dr); var cacheKey = "ForEachDataReader"+typeof(T).GetHashCode()+string.Join(",", columns.Select(it => it.Item1+it.Item2.Name+"_")); IDataReaderEntityBuilder entytyList = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate("cacheKey", () => { var cacheResult = new IDataReaderEntityBuilder(this.Context, dr, columns.Select(it=>it.Item1).ToList()).CreateBuilder(typeof(T)); return cacheResult; }); using (dr) { while (dr.Read()) { var order = entytyList.Build(dr); action(order); } } if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) { this.Context.Ado.Close(); } } public async Task ForEachDataReaderAsync(Action action) { var queryable = this.Clone(); var sql = queryable.ToSql(); var dr =await this.Context.Ado.GetDataReaderAsync(sql.Key, sql.Value); var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(); var columns = UtilMethods.GetColumnInfo(dr); var cacheKey = "ForEachDataReader" + typeof(T).GetHashCode() + string.Join(",", columns.Select(it => it.Item1 + it.Item2.Name + "_")); IDataReaderEntityBuilder entytyList = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate("cacheKey", () => { var cacheResult = new IDataReaderEntityBuilder(this.Context, dr, columns.Select(it => it.Item1).ToList()).CreateBuilder(typeof(T)); return cacheResult; }); using (dr) { while (dr.Read()) { var order = entytyList.Build(dr); action(order); } } if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) { this.Context.Ado.Close(); } } public virtual void ForEach(Action 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 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 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 virtual List ToOffsetPage(int pageIndex, int pageSize, ref int totalNumber, ref int totalPage) { var result = ToOffsetPage(pageIndex, pageSize, ref totalNumber); totalPage = (totalNumber + pageSize - 1) / pageSize; return result; } public List 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> 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 ToPageList(int pageIndex, int pageSize) { pageIndex = _PageList(pageIndex, pageSize); return ToList(); } public virtual List ToPageList(int pageIndex, int pageSize, ref int totalNumber, Expression> 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 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 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() { if (this.EntityInfo?.Type?.IsInterface==true) { this.QueryBuilder.SelectValue = " * "; this.AsType(this.EntityInfo.Type); } 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> ToSql() { if (!QueryBuilder.IsClone) { var newQueryable = this.Clone(); newQueryable.QueryBuilder.IsClone = true; return newQueryable.ToSql(); } else { return _ToSql(); } } public string ToClassString(string className) { List columns = new List(); 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; } public int IntoTable() { return IntoTable(typeof(TableEntityType)); } public int IntoTable(string TableName) { return IntoTable(typeof(TableEntityType), TableName); } public int IntoTable(Type TableEntityType) { var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(TableEntityType); var name = this.SqlBuilder.GetTranslationTableName(entityInfo.DbTableName); return IntoTable(TableEntityType, name); } public int IntoTable(Type TableEntityType,string TableName) { KeyValuePair> sqlInfo; string sql; OutIntoTableSql(TableName, out sqlInfo, out sql, TableEntityType); return this.Context.Ado.ExecuteCommand(sql, sqlInfo.Value); } } }