Update Subquery.ToList

This commit is contained in:
sunkaixuan
2022-12-03 19:57:56 +08:00
parent edff98d82b
commit 6e135307e0
9 changed files with 202 additions and 80 deletions

View File

@@ -10,6 +10,7 @@ namespace SqlSugar
{
public partial class DbBindAccessory
{
public QueryBuilder QueryBuilder { get; set; }
protected List<T> GetEntityList<T>(SqlSugarProvider context, IDataReader dataReader)
{
Type type = typeof(T);
@@ -29,6 +30,7 @@ namespace SqlSugar
while (dataReader.Read())
{
result.Add(entytyList.Build(dataReader));
SetAppendColumns(dataReader);
}
ExecuteDataAfterFun(context, dataAfterFunc, result);
}
@@ -39,6 +41,27 @@ namespace SqlSugar
return result;
}
private void SetAppendColumns(IDataReader dataReader)
{
if (QueryBuilder!=null&&QueryBuilder.AppendColumns != null && QueryBuilder.AppendColumns.Any())
{
if(QueryBuilder.AppendValues==null)
QueryBuilder.AppendValues = new List<List<QueryableAppendColumn>>();
List<QueryableAppendColumn> addItems = new List<QueryableAppendColumn>();
foreach (var item in QueryBuilder.AppendColumns)
{
var vi = dataReader.GetOrdinal(item.AsName);
var value = dataReader.GetValue(vi);
addItems.Add(new QueryableAppendColumn() {
Name=item.Name,
AsName=item.AsName,
Value=value
});
}
QueryBuilder.AppendValues.Add(addItems);
}
}
protected async Task<List<T>> GetEntityListAsync<T>(SqlSugarProvider context, IDataReader dataReader)
{
Type type = typeof(T);

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SqlSugar
{
internal class QueryableAppendColumn
{
public string AsName { get; set; }
public int Index { get; set; }
public object Value { get; set; }
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SqlSugar
{
internal class SqlInfo
{
public int? Take { get; set; }
public int? Skip { get; set; }
public string WhereString { get; set; }
public string OrderByString { get; set; }
public string SelectString { get; set; }
public List<SugarParameter> Parameters { get; set; }
public List<MappingFieldsExpression> MappingExpressions { get; set; }
public string TableShortName { get; set; }
}
}

View File

@@ -792,17 +792,5 @@ namespace SqlSugar
return shortName;
}
public class SqlInfo
{
public int? Take { get; set; }
public int? Skip { get; set; }
public string WhereString { get; set; }
public string OrderByString { get; set; }
public string SelectString { get; set; }
public List<SugarParameter> Parameters { get; set; }
public List<MappingFieldsExpression> MappingExpressions { get; set; }
public string TableShortName { get; set; }
}
}
}

View File

@@ -13,6 +13,9 @@ using System.Collections.ObjectModel;
using NetTaste;
using Newtonsoft.Json.Linq;
using System.Xml.Linq;
using Npgsql.Schema;
using MySql.Data.MySqlClient;
using System.Data.SqlTypes;
namespace SqlSugar
{
@@ -1224,6 +1227,7 @@ namespace SqlSugar
private List<TResult> GetData<TResult>(bool isComplexModel, Type entityType, IDataReader dataReader)
{
List<TResult> result;
this.Bind.QueryBuilder = this.QueryBuilder;
if (entityType == UtilConstants.DynamicType)
{
result = this.Context.Utilities.DataReaderToExpandoObjectList(dataReader) as List<TResult>;
@@ -1254,6 +1258,7 @@ namespace SqlSugar
private async Task<List<TResult>> GetDataAsync<TResult>(bool isComplexModel, Type entityType, IDataReader dataReader)
{
List<TResult> result;
this.Bind.QueryBuilder = this.QueryBuilder;
if (entityType == UtilConstants.DynamicType)
{
result = await this.Context.Utilities.DataReaderToExpandoObjectListAsync(dataReader) as List<TResult>;
@@ -1402,6 +1407,7 @@ namespace SqlSugar
#endregion
#region Subquery
private void _SubQuery<TResult>(List<TResult> result)
{
var isSubToList = this.QueryBuilder.SubToListParameters != null && this.QueryBuilder.SubToListParameters.Any();
@@ -1409,74 +1415,89 @@ namespace SqlSugar
{
return;
}
var isAuto = this.Context.CurrentConnectionConfig.IsAutoCloseConnection;
if(!this.Context.Ado.IsAnyTran())
this.Context.CurrentConnectionConfig.IsAutoCloseConnection = false;
Console.WriteLine("Subquery long link start");
var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(this.QueryBuilder.EntityType);
foreach (var paramter in this.QueryBuilder.SubToListParameters)
var appendValues = this.QueryBuilder.AppendValues;
var subParamters = this.QueryBuilder.SubToListParameters;
foreach (var subPara in subParamters)
{
for (int i = 0; i < result.Count; i++)
{
var ps = this.QueryBuilder.Parameters.ToList();
var item = result[i];
var sqlPart = paramter.Value.ObjToString();
int j = 0;
foreach (var column in entityInfo.Columns)
{
j++;
if (column.DbColumnName == null) continue;
var isumber = UtilMethods.IsNumber(column.PropertyInfo.PropertyType.Name);
var name = this.SqlBuilder.GetTranslationColumnName(this.QueryBuilder.TableShortName) + "." + this.SqlBuilder.GetTranslationColumnName(column.DbColumnName);
var guid = Guid.NewGuid() + "-" + Guid.NewGuid();
var oldLength = sqlPart.Length;
sqlPart = sqlPart.Replace(name, guid);
var newLength = sqlPart.Length;
if (oldLength != newLength)
{
PropertyInfo property = item.GetType().GetProperties().FirstOrDefault(it => it.Name.Equals(column.PropertyName));
Check.ExceptionEasy(property == null, $"The subquery condition uses {column.PropertyName}, so the Select DTO must have a {column.PropertyName} column", $"子查询条件用到了{column.PropertyName},所以 Select DTO 中必须要有 {column.PropertyName} 列");
var parameterName = this.SqlBuilder.SqlParameterKeyWord + "sublistp" +column.PropertyName+ j;
var parameter = new SugarParameter(parameterName, property.GetValue(item));
ps.Add(parameter);
sqlPart = sqlPart.Replace(guid, parameterName);
}
}
//sqlPart = sqlPart.Replace("@SugarlistRowIndex", 0);
var methodParamters = new object[] { sqlPart, ps };
var itemProperty = item.GetType().GetProperty(paramter.Key);
var callType = itemProperty.PropertyType.GetGenericArguments()[0];
var subList = ExpressionBuilderHelper.CallFunc(callType, methodParamters, this, "SubQueryList");
if (item.GetType().IsAnonymousType())
{
var jobj = JObject.FromObject(item);
var prop = jobj.Property(paramter.Key);
prop.Value = JArray.FromObject(subList);
result[i] = jobj.ToObject<TResult>();
}
else
{
itemProperty.SetValue(item, subList);
}
++i;
}
}
Console.WriteLine("Subquery long link end");
if (!this.Context.Ado.IsAnyTran())
{
this.Context.CurrentConnectionConfig.IsAutoCloseConnection = isAuto;
if (isAuto)
{
this.Context.Close();
}
if (appendValues != null)
AppendSubWhereToList(result, appendValues, subPara);
else
AppendSubToList(result, appendValues, subPara);
}
}
private void AppendSubToList<TResult>(List<TResult> result, List<List<QueryableAppendColumn>> appendValues, KeyValuePair<string, object> subPara)
{
var ps = this.QueryBuilder.PartitionByTemplate;
var itemProperty = typeof(TResult).GetProperty(subPara.Key);
var callType = itemProperty.PropertyType.GetGenericArguments()[0];
var methodParamters = new object[] { subPara.Value.ObjToString().Replace("@sugarIndex", "0"), ps };
var subList = ExpressionBuilderHelper.CallFunc(callType, methodParamters, this.Clone(), "SubQueryList");
foreach (var item in result)
{
var setValue = Activator.CreateInstance(itemProperty.PropertyType, true) as IList;
itemProperty.SetValue(item, subList);
}
}
private void AppendSubWhereToList<TResult>(List<TResult> result, List<List<QueryableAppendColumn>> appendValues, KeyValuePair<string, object> subPara)
{
var ps = this.QueryBuilder.PartitionByTemplate;
var index = 0;
List<string> sqls = new List<string>();
foreach (var item in result)
{
var sql = subPara.Value.ObjToString();
var replaceValues = appendValues[index];
foreach (var re in replaceValues)
{
var config = this.Context.CurrentConnectionConfig;
var p = new SugarParameter[] {
new SugarParameter("@p",re.Value)
};
var value = UtilMethods.GetSqlString(config.DbType, "@p", p, true);
sql = sql.Replace(re.Name, value);
}
sql = sql.Replace("@sugarIndex", index + "");
sqls.Add(sql);
index++;
}
var itemProperty = typeof(TResult).GetProperty(subPara.Key);
var callType = itemProperty.PropertyType.GetGenericArguments()[0];
var sqlstring = string.Join(" \r\n UNION ALL ", sqls);
var methodParamters = new object[] { sqlstring,ps};
this.QueryBuilder.SubToListParameters = null;
this.QueryBuilder.AppendColumns = new List<QueryableAppendColumn>() {
new QueryableAppendColumn(){ Name="sugarIndex",AsName="sugarIndex" }
};
this.QueryBuilder.AppendValues = null;
var subList = ExpressionBuilderHelper.CallFunc(callType, methodParamters, this.Clone(), "SubQueryList");
var appendValue = this.QueryBuilder.AppendValues;
var list = (subList as IEnumerable).Cast<object>().ToList();
var resIndex = 0;
foreach (var item in result)
{
var setValue = Activator.CreateInstance(itemProperty.PropertyType, true) as IList;
var appindex = 0;
foreach (var appValue in appendValue)
{
if (appValue[0].Value.ObjToInt() == resIndex)
{
var addItem = list[appindex];
setValue.Add(addItem);
}
appindex++;
}
itemProperty.SetValue(item, setValue);
resIndex++;
}
}
private async Task _SubQueryAsync<TResult>(List<TResult> result)
{
var isSubToList = this.QueryBuilder.SubToListParameters != null && this.QueryBuilder.SubToListParameters.Any();
@@ -1488,7 +1509,7 @@ namespace SqlSugar
}
public List<Type> SubQueryList<Type>(string sql,object parameters)
{
return this.Context.Ado.SqlQuery<Type>(sql,parameters);
return this.Context.Ado.SqlQuery<Type>(sql);
}
#endregion
}

View File

@@ -1,4 +1,5 @@
using System;
using NetTaste;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
@@ -34,6 +35,8 @@ namespace SqlSugar
#region Splicing basic
public Dictionary<string, object> SubToListParameters { get; set; }
internal List<QueryableAppendColumn> AppendColumns { get; set; }
internal List<List<QueryableAppendColumn>> AppendValues { get; set; }
public bool IsCrossQueryWithAttr { get; set; }
public Dictionary<string,string> CrossQueryItems { get; set; }
public bool IsSelectSingleFiledJson { get; set; }
@@ -608,6 +611,53 @@ namespace SqlSugar
{
result = " DISTINCT " + result;
}
if (this.SubToListParameters!=null&& this.SubToListParameters.Any())
{
List<string> names = new List<string>();
var allShortName = new List<string>();
allShortName.Add(this.Builder.SqlTranslationLeft+ Builder.GetNoTranslationColumnName(this.TableShortName.ObjToString().ToLower()+this.Builder.SqlTranslationRight+"."));
if (this.JoinQueryInfos.HasValue())
{
foreach (var item in this.JoinQueryInfos)
{
allShortName.Add(this.Builder.SqlTranslationLeft + Builder.GetNoTranslationColumnName(item.ShortName.ObjToString().ToLower() + this.Builder.SqlTranslationRight + "."));
}
}
else if (this.EasyJoinInfos!=null&& this.EasyJoinInfos.Any())
{
Check.ExceptionEasy("No Supprt Subquery.ToList(), Inner Join Or Left Join","Subquery.ToList请使用Inner方式联表");
}
if (this.TableShortName == null)
{
//Empty
}
else
{
var name = Builder.GetTranslationColumnName(this.TableShortName) + @"\.";
foreach (var paramter in this.SubToListParameters)
{
var regex = $@"\{Builder.SqlTranslationLeft}[\w]{{1,20}}?\{Builder.SqlTranslationRight}\.\{Builder.SqlTranslationLeft}.{{1,50}}?\{Builder.SqlTranslationRight}";
var matches = Regex
.Matches(paramter.Value.ObjToString(), regex, RegexOptions.IgnoreCase).Cast<Match>()
.Where(it => allShortName.Any(z => it.Value.ObjToString().ToLower().Contains(z)))
.Select(it => it.Value).ToList();
names.AddRange(matches);
}
int i = 0;
names = names.Distinct().ToList();
if (names.Any())
{
List<QueryableAppendColumn> colums = new List<QueryableAppendColumn>();
foreach (var item in names)
{
result = (result + $",{item} as app_ext_col_{i}");
colums.Add(new QueryableAppendColumn() { AsName = $"app_ext_col_{i}", Name = item, Index = i });
i++;
}
this.AppendColumns = colums;
}
}
}
return result;
}
}

View File

@@ -46,7 +46,7 @@ namespace SqlSugar
var exp = expression as MethodCallExpression;
InitType(exp);
if (exp.Arguments.Count == 0)
return "*";
return "*,@sugarIndex as sugarIndex";
var argExp = exp.Arguments[0];
var parametres = (argExp as LambdaExpression).Parameters;
if ((argExp as LambdaExpression).Body is UnaryExpression)
@@ -61,7 +61,7 @@ namespace SqlSugar
this.Context.Index = copyContext.Index;
this.Context.ParameterIndex = copyContext.ParameterIndex;
SetShortName(exp, null);
return select;
return select+",@sugarIndex as sugarIndex";
}
private void InitType(MethodCallExpression exp)

View File

@@ -9,6 +9,7 @@ namespace SqlSugar
{
public partial interface IDbBind
{
QueryBuilder QueryBuilder { get; set; }
SqlSugarProvider Context { get; set; }
List<string> GuidThrow { get; }
List<string> IntThrow { get; }

View File

@@ -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\Entities\QueryableAppendColumn.cs" />
<Compile Include="Abstract\QueryableProvider\Entities\SqlInfo.cs" />
<Compile Include="Abstract\QueryableProvider\QueryableExecuteSqlAsync.cs" />
<Compile Include="Abstract\QueryableProvider\QueryableExecuteSql.cs" />
<Compile Include="Abstract\QueryableProvider\QueryableProperties.cs" />