| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Text;
- using System.Threading.Tasks;
- namespace SqlSugar
- {
- internal class NavSelectHelper
- {
- internal static List<TResult> GetList<T, TResult>(Expression<Func<T, TResult>> expression, QueryableProvider<T> queryableProvider)
- {
-
- List<TResult> result = new List <TResult>();
- var isSqlFunc = IsSqlFunc(expression, queryableProvider);
- var isClass = IsClass(expression, queryableProvider);
- if (isGroup(expression, queryableProvider))
- {
- var sqlfuncQueryable = queryableProvider.Clone();
- sqlfuncQueryable.QueryBuilder.Includes = null;
- result = sqlfuncQueryable
- .Select(expression)
- .ToList();
- var includeQueryable = queryableProvider.Clone();
- includeQueryable.Select(GetGroupSelect(typeof(T), queryableProvider.Context, queryableProvider.QueryBuilder));
- includeQueryable.QueryBuilder.NoCheckInclude = true;
- var mappingColumn = GetMappingColumn(expression);
- MegerList(result, includeQueryable.ToList(), sqlfuncQueryable.Context, mappingColumn);
- }
- else if (isSqlFunc)
- {
- result = SqlFunc(expression, queryableProvider);
- }
- else if (typeof(TResult).IsAnonymousType() && isClass == false)
- {
- result = SqlFunc(expression, queryableProvider);
- }
- else if (typeof(TResult).IsAnonymousType() && isClass == true)
- {
- result = Action(expression, queryableProvider);
- }
- else if (expression.ToString().Contains("FirstOrDefault()"))
- {
- result = Action(expression, queryableProvider);
- }
- else
- {
- try
- {
- result = SqlFunc(expression, queryableProvider);
- }
- catch (Exception ex)
- {
- try
- {
- Console.WriteLine("Select DTO error . Warning:" + ex.Message);
- result = Action(expression, queryableProvider);
- }
- catch
- {
- throw;
- }
- }
- }
- return result;
- }
- private static List<TResult> Action<T, TResult>(Expression<Func<T, TResult>> expression, QueryableProvider<T> queryableProvider)
- {
- List<TResult> result;
- var entity = queryableProvider.Context.EntityMaintenance.GetEntityInfo<TResult>();
- var list = queryableProvider.Clone().ToList();
- var dt=queryableProvider.Context.Utilities.ListToDataTable(list);
- foreach (System.Data.DataRow item in dt.Rows)
- {
- foreach (System.Data.DataColumn columnInfo in dt.Columns)
- {
- if (columnInfo.DataType.IsClass())
- {
- if (item[columnInfo.ColumnName] == null || item[columnInfo.ColumnName] == DBNull.Value)
- {
- item[columnInfo.ColumnName] = Activator.CreateInstance(columnInfo.DataType, true);
- }
- }
- }
- }
- list = queryableProvider.Context.Utilities.DataTableToList<T>(dt);
- result = list.Select(expression.Compile()).ToList();
- return result;
- }
- private static List<TResult> SqlFunc<T, TResult>(Expression<Func<T, TResult>> expression, QueryableProvider<T> queryableProvider)
- {
- var mappingColumn = GetMappingColumn(expression);
- if (mappingColumn.Any(it => it.IsError))
- {
- return Action(expression,queryableProvider);
- }
- List<TResult> result;
- var sqlfuncQueryable = queryableProvider.Clone();
- var dtoEntity = sqlfuncQueryable.Context.EntityMaintenance.GetEntityInfo<TResult>().Columns;
- var tableEntity = sqlfuncQueryable.Context.EntityMaintenance.GetEntityInfo<T>().Columns;
- var ignoreColumns = GetIgnoreColumns(dtoEntity,tableEntity);
- sqlfuncQueryable.QueryBuilder.Includes = null;
- result = sqlfuncQueryable
- .IgnoreColumns(ignoreColumns)
- .Select(expression)
- .ToList();
- var selector = GetDefaultSelector(queryableProvider.Context.EntityMaintenance.GetEntityInfo<T>(), queryableProvider.QueryBuilder);
- var queryable = queryableProvider.Select(selector).Clone();
- queryable.QueryBuilder.NoCheckInclude = true;
- var includeList = queryable.ToList();
- MegerList(result, includeList, sqlfuncQueryable.Context,mappingColumn);
- return result;
- }
- private static string[] GetIgnoreColumns(List<EntityColumnInfo> dtoEntity, List<EntityColumnInfo> tableEntity)
- {
- var column = (from dto in dtoEntity
- join tab in tableEntity on dto.PropertyInfo.PropertyType equals tab.PropertyInfo.PropertyType
- where tab.Navigat!=null
- select tab.PropertyName).Distinct().ToArray();
- return column;
- }
- internal static async Task<List<TResult>> GetListAsync<T, TResult>(Expression<Func<T, TResult>> expression, QueryableProvider<T> queryableProvider)
- {
- return await Task.Run(()=> { return GetList(expression,queryableProvider); });
- }
- private static string GetGroupSelect(Type type,SqlSugarProvider context,QueryBuilder queryBuilder)
- {
- var entity = context.EntityMaintenance.GetEntityInfo(type);
- List<string> selector = new List<string>();
- List<EntityColumnInfo> columns = GetListNavColumns(entity);
- foreach (var item in columns)
- {
- if (queryBuilder.TableShortName.HasValue())
- {
- selector.Add($" min({queryBuilder.TableShortName}.{item.DbColumnName}) as {item.DbColumnName}");
- }
- else
- {
- selector.Add($" min({item.DbColumnName}) as {item.DbColumnName}");
- }
- }
- return string.Join(",", selector);
- }
- private static string GetDefaultSelector(EntityInfo entityInfo, QueryBuilder queryBuilder)
- {
- List<EntityColumnInfo> columns = GetListNavColumns(entityInfo);
- var selector = new List<string>();
- if (columns.Count == 0) return null;
- foreach (var item in columns)
- {
- if (queryBuilder.TableShortName.HasValue())
- {
- selector.Add($" {queryBuilder.TableShortName}.{item.DbColumnName} as {item.DbColumnName}");
- }
- else
- {
- selector.Add($" {item.DbColumnName} as {item.DbColumnName}");
- }
- }
- return string.Join(",", selector);
- }
- private static List<EntityColumnInfo> GetListNavColumns(EntityInfo entityInfo)
- {
- var list = entityInfo.Columns.Where(it => it.Navigat != null).Select(
- it => it.Navigat.Name
- ).ToArray();
- var list2 = entityInfo.Columns.Where(it => it.Navigat != null && it.Navigat.Name2 != null).Select(
- it => it.Navigat.Name2
- ).ToArray();
- var columns = entityInfo.Columns.Where(it => it.IsPrimarykey ||
- list.Contains(it.PropertyName) ||
- list2.Contains(it.PropertyName)
- ).ToList();
- return columns;
- }
- private static void MegerList<TResult, T>(List<TResult> result, List<T> includeList,SqlSugarProvider context,List<NavMappingColumn> navMappingColumns)
- {
- if (result.Count != includeList.Count) return;
- var columns = context.EntityMaintenance.GetEntityInfo<T>().Columns;
- var resColumns = context.EntityMaintenance.GetEntityInfo<TResult>().Columns;
- var i = 0;
- foreach (var item in includeList)
- {
- foreach (var column in columns)
- {
- if (column.Navigat != null)
- {
- var value = column.PropertyInfo.GetValue(item);
- var resColumn=resColumns
- .FirstOrDefault(z=>
- z.PropertyName.Equals(column.PropertyName)&&
- z.PropertyInfo.PropertyType==column.PropertyInfo.PropertyType
- );
- if (resColumn == null && navMappingColumns.Any(z => z.Value == column.PropertyName))
- {
- var mappingColumn = navMappingColumns.First(z => z.Value == column.PropertyName);
- resColumn = resColumns
- .FirstOrDefault(z =>
- z.PropertyName.Equals(mappingColumn.Key) &&
- z.PropertyInfo.PropertyType == column.PropertyInfo.PropertyType
- );
- }
- if (resColumn != null)
- {
- var resItem= result[i];
- resColumn.PropertyInfo.SetValue(resItem,value);
- }
- }
- }
- i++;
- }
- }
- private static bool IsClass<T, TResult>(Expression<Func<T, TResult>> expression, QueryableProvider<T> queryableProvider)
- {
- var body = ExpressionTool.GetLambdaExpressionBody(expression);
- if (body is NewExpression)
- {
- var newExp = ((NewExpression)body);
- foreach (var item in newExp.Arguments)
- {
- if (item is MemberExpression)
- {
- var member = (MemberExpression)item;
- if (member.Type.IsClass())
- {
- return true;
- }
- }
- }
- }
- return false;
- }
- private static bool IsSqlFunc<T, TResult>(Expression<Func<T, TResult>> expression, QueryableProvider<T> queryableProvider)
- {
- var body=ExpressionTool.GetLambdaExpressionBody(expression);
- if (body is NewExpression)
- {
- var newExp=((NewExpression)body);
- foreach (var item in newExp.Arguments)
- {
- if (item is MethodCallExpression)
- {
- var method = ((MethodCallExpression)item).Method;
- if (method.DeclaringType != null&& method.DeclaringType.Name=="SqlFunc")
- {
- return true;
- }
- }
- }
- }
- if (body is MemberInitExpression)
- {
- var newExp = ((MemberInitExpression)body);
- foreach (var item in newExp.Bindings)
- {
- MemberAssignment memberAssignment = (MemberAssignment)item;
- if (memberAssignment.Expression is MethodCallExpression)
- {
- var method = ((MethodCallExpression)memberAssignment.Expression).Method;
- if (method.DeclaringType != null && method.DeclaringType.Name == "SqlFunc")
- {
- return true;
- }
- }
- }
- }
- return false;
- }
- private static List<NavMappingColumn> GetMappingColumn(Expression expression)
- {
- var body = ExpressionTool.GetLambdaExpressionBody(expression);
- var parameterName=(expression as LambdaExpression).Parameters.FirstOrDefault().Name;
- List<NavMappingColumn> result = new List<NavMappingColumn>();
- if (body is NewExpression)
- {
- var index = 0;
- var arg = ((NewExpression)body).Arguments;
- var members = ((NewExpression)body).Members;
- foreach (var item in arg)
- {
- var name=members[index].Name;
- if (item is MethodCallExpression)
- {
- AddCallError(result, item, parameterName);
- }
- index++;
- }
- }
- else if (body is MemberInitExpression)
- {
- foreach (var item in ((MemberInitExpression)body).Bindings)
- {
- MemberAssignment memberAssignment = (MemberAssignment)item;
- var key= memberAssignment.Member.Name;
- var value = memberAssignment.Expression;
- if (memberAssignment.Expression is MemberExpression)
- {
- result.Add(new NavMappingColumn() { Key = key, Value = ExpressionTool.GetMemberName(memberAssignment.Expression) });
- }
- else if(memberAssignment.Expression is MethodCallExpression)
- {
- AddCallError(result, memberAssignment.Expression,parameterName);
- }
- }
- }
- return result;
- }
- private static void AddCallError(List<NavMappingColumn> result, Expression item,string parameterName)
- {
- var method = (item as MethodCallExpression);
- if (method.Method.Name == "ToList" && method.Arguments.Count > 0 && method.Arguments[0] is MethodCallExpression)
- {
- method = (MethodCallExpression)method.Arguments[0];
- }
- if (method.Method.Name == "Select")
- {
- if (!item.ToString().Contains("Subqueryable"))
- {
- result.Add(new NavMappingColumn() { IsError = true });
- }
- }
- else if (method.Method.Name == "Join")
- {
-
- if (item.ToString().Contains($" {parameterName}."))
- {
- result.Add(new NavMappingColumn() { IsError = true });
- }
- }
- }
- private static bool isGroup<T, TResult>(Expression<Func<T, TResult>> expression, QueryableProvider<T> queryableProvider)
- {
- var isGroup=queryableProvider.QueryBuilder.GetGroupByString.HasValue();
- return isGroup;
- }
- internal class NavMappingColumn
- {
- public string Key { get; set; }
- public string Value { get; set; }
- public bool IsError { get; set; }
- }
- }
- }
|