internal object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index) { if (parent.Childs.Any() == false) { return(dr.GetValue(++index)); } switch (parent.ConsturctorType) { case ReadAnonymousTypeInfoConsturctorType.Arguments: var args = new object[parent.Childs.Count]; for (var a = 0; a < parent.Childs.Count; a++) { args[a] = Utils.GetDataReaderValue(parent.Childs[a].CsType, ReadAnonymous(parent.Childs[a], dr, ref index)); } return(parent.Consturctor.Invoke(args)); case ReadAnonymousTypeInfoConsturctorType.Properties: var ret = parent.Consturctor.Invoke(null); for (var b = 0; b < parent.Childs.Count; b++) { var prop = parent.Childs[b].Property; prop.SetValue(ret, Utils.GetDataReaderValue(prop.PropertyType, ReadAnonymous(parent.Childs[b], dr, ref index)), null); } return(ret); } return(null); }
public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp, List <SelectTableInfo> tables) { _select = select; _map = map; _comonExp = comonExp; _tables = tables; }
public SelectGroupingProvider(IFreeSql orm, Select0Provider select, ReadAnonymousTypeInfo map, string field, CommonExpression comonExp, List <SelectTableInfo> tables) { _orm = orm; _select = select; _map = map; _field = field; _comonExp = comonExp; _tables = tables; }
public string InternalToSql(Expression select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0; _comonExp.ReadAnonymousField(null, field, map, ref index, select, null, this, null, null, false); var fieldSql = field.Length > 0 ? field.Remove(0, 2).ToString() : null; return(InternalToSql(fieldSql)); }
public List <TReturn> ToList <TReturn>(Expression <Func <ISelectGroupingAggregate <TKey, TValue>, TReturn> > select) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString); var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TReturn)); return(method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as List <TReturn>);
public string InternalToSql(Expression select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0; _comonExp.ReadAnonymousField(null, field, map, ref index, select, null, this, null, null, false); var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) }); return(method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string); }
public string ToSql <TReturn>(Expression <Func <ISelectGroupingAggregate <TKey, TValue>, TReturn> > select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0; _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, true); var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) }); return(method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string); }
public SelectedQueryProvider(Select0Provider select, Expression selector) { _select = select; _comonExp = _select._commonExpression; _map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = -10000; //临时规则,不返回 as1 if (selector != null) { _comonExp.ReadAnonymousField(_select._tables, field, _map, ref index, selector, null, null, _select._whereGlobalFilter, null, false); //不走 DTO 映射,不处理 IncludeMany } _field = field.ToString(); }
public object InternalToList(Expression select, Type elementType) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; _comonExp.ReadAnonymousField(null, field, map, ref index, select, null, this, null, null, false); if (map.Childs.Any() == false && map.MapType == null) { map.MapType = elementType; } var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(elementType); return(method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) })); }
public Task <List <TReturn> > ToListAsync <TReturn>(Expression <Func <ISelectGroupingAggregate <TKey, TValue>, TReturn> > select) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, true); if (map.Childs.Any() == false && map.MapType == null) { map.MapType = typeof(TReturn); } var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TReturn)); return(method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task <List <TReturn> >); }
public IEnumerable <KeyValuePair <object, object> > InternalToKeyValuePairs(Expression elementSelector, Type elementType) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; _comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, null, this, null, null, false); if (map.Childs.Any() == false && map.MapType == null) { map.MapType = elementType; } var method = _select.GetType().GetMethod("ToListMapReaderPrivate", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(elementType); var otherAf = new ReadAnonymousTypeOtherInfo(_field, _map, new List <object>()); var values = method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null), new[] { otherAf } }) as IList; return(otherAf.retlist.Select((a, b) => new KeyValuePair <object, object>(a, values[b]))); }
public TResult Execute <TResult>(Expression expression) { var stackCallExps = new Stack <MethodCallExpression>(); var callExp = expression as MethodCallExpression; while (callExp != null) { stackCallExps.Push(callExp); callExp = callExp?.Arguments.FirstOrDefault() as MethodCallExpression; } SelectGroupingProvider groupBy = null; var isfirst = false; while (stackCallExps.Any()) { callExp = stackCallExps.Pop(); TResult throwCallExp(string message) => throw new Exception($"FreeSql Queryable 解析出错,执行的方法 {callExp.Method.Name} {message}"); if (callExp.Method.DeclaringType != typeof(Queryable)) { return(throwCallExp($"必须属于 System.Linq.Queryable")); } TResult tplMaxMinAvgSum(string method) { if (callExp.Arguments.Count == 2) { var avgParam = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression; return((TResult)Utils.GetDataReaderValue(typeof(TResult), _select.GetType().GetMethod(method).MakeGenericMethod(avgParam.ReturnType).Invoke(_select, new object[] { avgParam }))); } return(throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法")); } TResult tplOrderBy(string method, bool isDescending) { if (callExp.Arguments.Count == 2) { var arg1 = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression; _select.OrderByReflection(arg1, isDescending); return(default(TResult)); } return(throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法")); } switch (callExp.Method.Name) { case "Any": if (callExp.Arguments.Count == 2) { _select.InternalWhere(callExp.Arguments[1]); } return((TResult)(object)_select.Any()); case "AsQueryable": break; case "Max": return(tplMaxMinAvgSum("Max")); case "Min": return(tplMaxMinAvgSum("Min")); case "Sum": return(tplMaxMinAvgSum("Sum")); case "Average": return(tplMaxMinAvgSum("Avg")); case "Concat": return(throwCallExp(" 不支持")); case "Contains": if (callExp.Arguments.Count == 2) { var dywhere = callExp.Arguments[1].GetConstExprValue(); if (dywhere == null) { return(throwCallExp($" 参数值不能为 null")); } _select.WhereDynamic(dywhere); return((TResult)(object)_select.Any()); } return(throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法")); case "Count": if (callExp.Arguments.Count == 2) { _select.InternalWhere(callExp.Arguments[1]); } return((TResult)Utils.GetDataReaderValue(typeof(TResult), _select.Count())); case "Distinct": if (callExp.Arguments.Count == 1) { _select.Distinct(); break; } return(throwCallExp(" 不支持")); case "ElementAt": case "ElementAtOrDefault": _select.Offset((int)callExp.Arguments[1].GetConstExprValue()); _select.Limit(1); isfirst = true; break; case "First": case "FirstOrDefault": case "Single": case "SingleOrDefault": if (callExp.Arguments.Count == 2) { _select.InternalWhere(callExp.Arguments[1]); } _select.Limit(1); isfirst = true; break; case "OrderBy": tplOrderBy("OrderByReflection", false); break; case "OrderByDescending": tplOrderBy("OrderByReflection", true); break; case "ThenBy": tplOrderBy("OrderByReflection", false); break; case "ThenByDescending": tplOrderBy("OrderByReflection", true); break; case "Where": var whereParam = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression; if (whereParam.Parameters.Count == 1) { if (groupBy != null) { groupBy.InternalHaving(whereParam); } else { _select.InternalWhere(whereParam); } break; } return(throwCallExp(" 不支持")); case "Skip": _select.Offset((int)callExp.Arguments[1].GetConstExprValue()); break; case "Take": _select.Limit((int)callExp.Arguments[1].GetConstExprValue()); break; case "ToList": if (callExp.Arguments.Count == 1) { return((TResult)(object)_select.ToList()); } return(throwCallExp(" 不支持")); case "Select": var selectParam = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression; if (selectParam.Parameters.Count == 1) { _select._selectExpression = selectParam; break; } return(throwCallExp(" 不支持")); case "Join": if (callExp.Arguments.Count == 5) { var arg2 = (callExp.Arguments[2] as UnaryExpression)?.Operand as LambdaExpression; var arg3 = (callExp.Arguments[3] as UnaryExpression)?.Operand as LambdaExpression; var arg4 = (callExp.Arguments[4] as UnaryExpression)?.Operand as LambdaExpression; FreeSqlExtensionsLinqSql.InternalJoin2(_select, arg2, arg3, arg4); _select._selectExpression = arg4.Body; break; } return(throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法")); case "GroupJoin": if (callExp.Arguments.Count == 5) { var arg2 = (callExp.Arguments[2] as UnaryExpression)?.Operand as LambdaExpression; var arg3 = (callExp.Arguments[3] as UnaryExpression)?.Operand as LambdaExpression; var arg4 = (callExp.Arguments[4] as UnaryExpression)?.Operand as LambdaExpression; FreeSqlExtensionsLinqSql.InternalJoin2(_select, arg2, arg3, arg4); _select._selectExpression = arg4.Body; break; } return(throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法")); case "SelectMany": if (callExp.Arguments.Count == 3) { var arg1 = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression; var arg2 = (callExp.Arguments[2] as UnaryExpression)?.Operand as LambdaExpression; FreeSqlExtensionsLinqSql.InternalSelectMany2(_select, arg1, arg2); _select._selectExpression = arg2.Body; break; } return(throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法")); case "DefaultIfEmpty": break; case "Last": case "LastOrDefault": return(throwCallExp(" 不支持")); case "GroupBy": return(throwCallExp(" 不支持")); if (callExp.Arguments.Count == 2) //TODO: 待实现 { var arg1 = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression; var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = -10000; //临时规则,不返回 as1 _select._commonExpression.ReadAnonymousField(_select._tables, field, map, ref index, arg1, null, _select._whereCascadeExpression, false); //不走 DTO 映射 var sql = field.ToString(); _select.GroupBy(sql.Length > 0 ? sql.Substring(2) : null); groupBy = new SelectGroupingProvider(_select._orm, _select, map, sql, _select._commonExpression, _select._tables); break; } return(throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法")); default: return(throwCallExp(" 不支持")); } } if (isfirst) { _select.Limit(1); if (_select._selectExpression != null) { return((TResult)(object)_select.InternalToList <TCurrent>(_select._selectExpression).FirstOrDefault()); } return((TResult)(object)_select.ToList().FirstOrDefault()); } if (_select._selectExpression != null) { return((TResult)(object)_select.InternalToList <TCurrent>(_select._selectExpression)); } return((TResult)(object)_select.ToList()); }
public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp) { _select = select; _map = map; _comonExp = comonExp; }
internal bool ReadAnonymousField(List <SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func <Expression[], string> getSelectGroupingMapString) { switch (exp.NodeType) { case ExpressionType.Quote: return(ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString)); case ExpressionType.Lambda: return(ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, getSelectGroupingMapString)); case ExpressionType.Negate: case ExpressionType.NegateChecked: parent.DbField = $"-({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true)})"; field.Append(", ").Append(parent.DbField); if (index >= 0) { field.Append(" as").Append(++index); } return(false); case ExpressionType.Convert: return(ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString)); case ExpressionType.Constant: var constExp = exp as ConstantExpression; //处理自定义SQL语句,如: ToList(new { // ccc = "now()", // partby = "sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)" //}),有缺点即 ccc partby 接受类型都是 string,可配合 Convert.ToXxx 类型转换,请看下面的兼容 parent.DbField = constExp.Type.FullName == "System.String" ? (constExp.Value?.ToString() ?? "NULL") : _common.FormatSql("{0}", constExp?.Value); field.Append(", ").Append(parent.DbField); if (index >= 0) { field.Append(" as").Append(++index); } return(false); case ExpressionType.Call: var callExp = exp as MethodCallExpression; //处理自定义SQL语句,如: ToList(new { // ccc = Convert.ToDateTime("now()"), // partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") //}) if (callExp.Method?.DeclaringType.FullName == "System.Convert" && callExp.Method.Name.StartsWith("To") && callExp.Arguments[0].NodeType == ExpressionType.Constant && callExp.Arguments[0].Type.FullName == "System.String") { parent.DbField = (callExp.Arguments[0] as ConstantExpression).Value?.ToString() ?? "NULL"; } else { parent.DbField = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true); } field.Append(", ").Append(parent.DbField); if (index >= 0) { field.Append(" as").Append(++index); } return(false); case ExpressionType.MemberAccess: if (_common.GetTableByEntity(exp.Type) != null) //加载表所有字段 { var map = new List <SelectColumnInfo>(); ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true, getSelectGroupingMapString); parent.Consturctor = map.First().Table.Table.Type.GetConstructor(new Type[0]); parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; for (var idx = 0; idx < map.Count; idx++) { var child = new ReadAnonymousTypeInfo { Property = map.First().Table.Table.Type.GetProperty(map[idx].Column.CsName, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance), CsName = map[idx].Column.CsName, DbField = $"{map[idx].Table.Alias}.{_common.QuoteSqlName(map[idx].Column.Attribute.Name)}" }; field.Append(", ").Append(_common.QuoteReadColumn(map[idx].Column.CsType, child.DbField)); if (index >= 0) { field.Append(" as").Append(++index); } parent.Childs.Add(child); } } else { parent.DbField = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true); field.Append(", ").Append(parent.DbField); if (index >= 0) { field.Append(" as").Append(++index); } return(false); } return(false); case ExpressionType.New: var newExp = exp as NewExpression; parent.Consturctor = newExp.Type.GetConstructors()[0]; parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Arguments; for (var a = 0; a < newExp.Members.Count; a++) { var child = new ReadAnonymousTypeInfo { Property = newExp.Type.GetProperty(newExp.Members[a].Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance), CsName = newExp.Members[a].Name, CsType = newExp.Arguments[a].Type }; parent.Childs.Add(child); ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], getSelectGroupingMapString); } return(true); } parent.DbField = $"({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true)})"; field.Append(", ").Append(parent.DbField); if (index >= 0) { field.Append(" as").Append(++index); } return(false); }