Пример #1
0
        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);
        }
Пример #2
0
 public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp, List <SelectTableInfo> tables)
 {
     _select   = select;
     _map      = map;
     _comonExp = comonExp;
     _tables   = tables;
 }
Пример #3
0
 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;
 }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #8
0
        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])));
        }
Пример #12
0
        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());
        }
Пример #13
0
 public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp)
 {
     _select   = select;
     _map      = map;
     _comonExp = comonExp;
 }
Пример #14
0
        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);
        }