private static QueryBuffer.TypeBuffer GetTypeBuffer(HarmonyTableExpression table, List <Tuple <HarmonyTableExpression, QueryBuffer.TypeBuffer> > flatList) { var queryTables = table.RootExpression.RootExpressions.Values.OfType <HarmonyTableExpression>().Where(qt => qt != table); var made = new QueryBuffer.TypeBuffer { DataObjectType = table.ItemType, IsCollection = table.IsCollection, ParentFieldName = table.Name, Metadata = DataObjectMetadataBase.LookupType(table.ItemType) }; if (table.Top != null) { var bakedFunction = Expression.Lambda <Func <QueryContext, long> >(Expression.Convert(table.Top, typeof(long)), QueryCompilationContext.QueryContextParameter).Compile(); made.Top = (obj) => bakedFunction(obj as QueryContext); } if (table.Skip != null) { var bakedFunction = Expression.Lambda <Func <QueryContext, long> >(Expression.Convert(table.Skip, typeof(long)), QueryCompilationContext.QueryContextParameter).Compile(); made.Skip = (obj) => bakedFunction(obj as QueryContext); } if (made.Top != null || made.Skip != null) { made.SelectResult = CollectionFilterMethod.MakeGenericMethod(made.DataObjectType).CreateDelegate(typeof(Func <QueryBuffer, QueryBuffer.TypeBuffer, object, object>), null) as Func <QueryBuffer, QueryBuffer.TypeBuffer, object, object>; } flatList.Add(Tuple.Create(table, made)); var joinedBuffers = queryTables.OfType <HarmonyTableExpression>().Where(qt => !qt.Name.Contains(".")).Select(qt => GetTypeBuffer(qt, flatList)).ToList(); var namedLookup = joinedBuffers.ToDictionary(tb => tb.ParentFieldName); foreach (var nestedTable in queryTables.OfType <HarmonyTableExpression>().Where(qt => qt.Name.Contains(".")).OrderBy(qt => qt.Name.Length)) { var nameParts = nestedTable.Name.Split("."); if (namedLookup.TryGetValue(string.Join(".", nameParts.Take(nameParts.Length - 1)), out var foundBuffer)) { var fullName = nestedTable.Name; nestedTable.Name = nameParts.Last(); var madeBuffer = GetTypeBuffer(nestedTable, flatList); foundBuffer.JoinedBuffers.Add(madeBuffer); namedLookup.Add(fullName, madeBuffer); } else { throw new Exception(string.Format("failed to find parent table while processing query {0}", nestedTable.Name)); } } made.JoinedBuffers = joinedBuffers; return(made); }
public HarmonyQueryExpression(IEntityType entityType) { Type = typeof(IQueryable <>).MakeGenericType(new Type[] { entityType.ClrType }); _valueBufferParameter = Parameter(typeof(DataObjectBase), "valueBuffer"); var rootTable = new HarmonyTableExpression(entityType, "", this); RootExpressions = new Dictionary <Expression, HarmonyTableExpression> { { CurrentParameter, rootTable } }; ServerQueryExpression = rootTable; //var readExpressionMap = new Dictionary<IProperty, Expression>(); //foreach (var property in entityType.GetAllBaseTypesInclusive().SelectMany(et => et.GetDeclaredProperties())) //{ // readExpressionMap[property] = CreateReadValueExpression(property.ClrType, property.GetIndex(), property); //} //foreach (var property in entityType.GetDerivedTypes().SelectMany(et => et.GetDeclaredProperties())) //{ // readExpressionMap[property] = CreateReadValueExpression(property.ClrType, property.GetIndex(), property); //} //var entityProjection = new EntityProjectionExpression(entityType, readExpressionMap); _projectionMapping[new ProjectionMember()] = ConvertedParameter = Expression.Convert(CurrentParameter, entityType.ClrType); }