public virtual IQueryable GetQuery(QuerySource source, QueryConfiguration config) { var propsToQuery = PropertyConfigurations.ToList(); if (config.Select.Any()) { var columns = config.Select.ToList(); var filterPaths = config.TargetFilterItems.SelectMany(p => p.GetValueExpressions()).OfType <PathValueExpression>().Select(p => p.Path).ToList(); var fromSortAndFilter = config.Sort.Select(p => p.PropertyPath).Concat(filterPaths) .Select(p => p.Split('.').First()).Distinct().ToList(); foreach (var missing in fromSortAndFilter.Where(p => !columns.Any(x => x.Property == p)).ToList()) { columns.Add(new SelectItem(missing)); } propsToQuery = (from p in PropertyConfigurations join c in columns on p.Property.Name equals c.Property select p).ToList(); } var columnDependencies = propsToQuery.SelectMany(p => p.DependsOn).Distinct().ToList(); var dict = new Dictionary <string, List <string> >(); ResolveDependencies(columnDependencies, dict); var sortedDependencies = new List <string>(); while (dict.Any()) { var items = dict.Where(p => !p.Value.Any()).OrderBy(p => p.Key).Select(p => p.Key).ToList(); if (!items.Any()) { throw new InvalidOperationException("Circular dependency found!"); } sortedDependencies.AddRange(items); foreach (var toRemove in items) { dict.Remove(toRemove); foreach (var item in dict) { item.Value.Remove(toRemove); } } } var param = Expression.Parameter(this.SourceType, "p"); IQueryable baseQuery = CreateBaseQuery(source, sortedDependencies); var filter = new FilterItemGroup(config.FilterItems); baseQuery = baseQuery.ApplyFilterItem(filter); var members = propsToQuery.ToDictionary(p => (MemberInfo)p.PropertyInfo, p => p.MappedExpression.Body.Replace(p.MappedExpression.Parameters.First(), param)); var initExpression = GetResultInitExpression(members); var selectExpresssion = Expression.Lambda(initExpression, param); var queryExpression = Expression.Call( QueryableInfo.Select.MakeGenericMethod(SourceType, ResultType), baseQuery.Expression, Expression.Quote(selectExpresssion)); baseQuery = baseQuery.Provider.CreateQuery(queryExpression); if (config.TargetFilterItems.Any()) { var targetFilter = new FilterItemGroup(config.TargetFilterItems); baseQuery = baseQuery.ApplyFilterItem(targetFilter); } if (config.Sort.Any()) { baseQuery = baseQuery.ApplySort(config.Sort); } return(baseQuery); }
public new IQueryable <TResult> GetQuery(QuerySource source, QueryConfiguration config) { return((IQueryable <TResult>)base.GetQuery(source, config)); }
private IQueryable CreateBaseQuery(QuerySource source, IEnumerable <string> sortedDependencies) { var sourceConfig = this.SourceEntityConfigurations.First(); if (sourceConfig.Name == null) { return(sourceConfig.QueryFactory(source)); } var allConfigs = sortedDependencies .Select(p => this.SourceEntityConfigurations.First(x => x.Name == p)) .Select(p => new { Key = p, Member = SourceType.GetProperty(p.Name) }).ToList(); var baseEntity = allConfigs.First(); var joined = allConfigs.Skip(1).ToList(); var baseQuery = baseEntity.Key.QueryFactory(source); var baseExpression = baseQuery.Expression; var param = Expression.Parameter(baseEntity.Key.EntityType, "p"); Dictionary <MemberInfo, Expression> memberInits = new Dictionary <MemberInfo, Expression>() { { baseEntity.Member, param } }; foreach (var item in joined) { memberInits.Add(item.Member, Expression.Constant(null, item.Key.EntityType)); } var body = GetInitExpression(SourceType, memberInits); baseExpression = Expression.Call( QueryableInfo.Select.MakeGenericMethod(baseEntity.Key.EntityType, SourceType), baseExpression, Expression.Quote(Expression.Lambda(body, param))); for (int i = 0; i < joined.Count; i++) { var entityType = joined[i].Key.EntityType; var joinPairType = typeof(GroupJoinPair <,>).MakeGenericType(SourceType, entityType); var localJoin = joined[i].Key.LocalJoinExpression; var remoteJoin = joined[i].Key.RemoteJoinExpression; var param1 = Expression.Parameter(SourceType, "p1"); var param2 = Expression.Parameter(typeof(IEnumerable <>).MakeGenericType(entityType), "p2"); var joinBody = Expression.MemberInit( Expression.New(joinPairType), Expression.Bind(joinPairType.GetProperty("Parent"), param1), Expression.Bind(joinPairType.GetProperty("Children"), param2)); var test = joined[i].Key.QueryFactory(source); ////Expression.Constant(, typeof(IQueryable<>).MakeGenericType(joined[i].Key.EntityType)), baseExpression = Expression.Call( QueryableInfo.GroupJoin.MakeGenericMethod(SourceType, entityType, joined[i].Key.JoinKeyType, joinPairType), baseExpression, test.Expression, remoteJoin, localJoin, Expression.Quote(Expression.Lambda(joinBody, param1, param2))); param1 = Expression.Parameter(joinPairType, "p1"); param2 = Expression.Parameter(entityType, "p2"); memberInits[baseEntity.Member] = Expression.Property(Expression.Property(param1, "Parent"), baseEntity.Key.Name); for (int j = 0; j < i; j++) { memberInits[joined[j].Member] = Expression.Property(Expression.Property(param1, "Parent"), joined[j].Key.Name); } memberInits[joined[i].Member] = param2; baseExpression = Expression.Call( QueryableInfo.SelectMany.MakeGenericMethod(joinPairType, entityType, SourceType), baseExpression, Expression.Lambda(Expression.Call(EnumerableInfo.DefaultIfEmpty.MakeGenericMethod(entityType), Expression.Property(param1, "Children")), param1), Expression.Lambda(GetInitExpression(SourceType, memberInits), param1, param2)); } return(baseQuery.Provider.CreateQuery(baseExpression)); }