private static IEnumerable <DataObjectBase> Table( QueryContext queryContext, IEntityType entityType, PreparedQueryPlan queryPlan) { Func <DataObjectBase, DataObjectBase> track = (obj) => { queryContext.StartTracking(entityType, obj, default(Microsoft.EntityFrameworkCore.Storage.ValueBuffer)); return(obj); }; if (queryPlan.IsCollection) { return(typeof(PreparedQueryPlan) .GetMethod("ExecuteCollectionPlan") .MakeGenericMethod(new Type[] { entityType.ClrType }) .Invoke(queryPlan, new object[] { track, ((HarmonyQueryContext)queryContext).ParameterValues, ((HarmonyQueryContext)queryContext).Store, queryContext }) as IEnumerable <DataObjectBase>); } else { var singleResult = typeof(PreparedQueryPlan) .GetMethod("ExecutePlan") .MakeGenericMethod(new Type[] { entityType.ClrType }) .Invoke(queryPlan, new object[] { track, ((HarmonyQueryContext)queryContext).ParameterValues, ((HarmonyQueryContext)queryContext).Store, queryContext }) as DataObjectBase; var arrayResult = Array.CreateInstance(entityType.ClrType, 1); arrayResult.SetValue(singleResult, 0); return(arrayResult as IEnumerable <DataObjectBase>); } }
private static IEnumerable <DataObjectBase> Table( QueryContext queryContext, IEntityType entityType, PreparedQueryPlan queryPlan, bool isTracking) { Func <DataObjectBase, DataObjectBase> track = (obj) => { if (isTracking) { var localType = entityType; if (entityType.ClrType != obj.GetType()) { localType = queryContext.Context.Model.FindEntityType(obj.GetType()); } var keyValues = localType.FindPrimaryKey().Properties.Select(prop => prop.GetGetter().GetClrValue(obj)).ToArray(); var foundEntry = queryContext.StateManager.TryGetEntry(localType.FindPrimaryKey(), keyValues); if (foundEntry != null && foundEntry.EntityState != EntityState.Detached) { return(foundEntry.Entity as DataObjectBase); } else { queryContext.StartTracking(localType, obj, default(Microsoft.EntityFrameworkCore.Storage.ValueBuffer)); } } return(obj); }; if (queryPlan.IsCollection) { return(typeof(PreparedQueryPlan) .GetMethod("ExecuteCollectionPlan") .MakeGenericMethod(new Type[] { entityType.ClrType }) .Invoke(queryPlan, new object[] { track, ((HarmonyQueryContext)queryContext).ParameterValues, ((HarmonyQueryContext)queryContext).Store, queryContext }) as IEnumerable <DataObjectBase>); } else { var singleResult = typeof(PreparedQueryPlan) .GetMethod("ExecutePlan") .MakeGenericMethod(new Type[] { entityType.ClrType }) .Invoke(queryPlan, new object[] { track, ((HarmonyQueryContext)queryContext).ParameterValues, ((HarmonyQueryContext)queryContext).Store, queryContext }) as DataObjectBase; var arrayResult = Array.CreateInstance(entityType.ClrType, 1); arrayResult.SetValue(singleResult, 0); return(arrayResult as IEnumerable <DataObjectBase>); } }
public PreparedQueryPlan PrepareQuery(HarmonyQueryCompilationContext compilationContext) { var rootExpr = RootExpressions[_valueBufferParameter]; var processedOns = new List <object>(); var flatList = new List <Tuple <HarmonyTableExpression, QueryBuffer.TypeBuffer> >(); var typeBuffers = new QueryBuffer.TypeBuffer[] { GetTypeBuffer(rootExpr, flatList) }; var expressionTableMapping = flatList.ToDictionary(kvp => kvp.Item1.RootExpression.ConvertedParameter as Expression, kvp => kvp.Item1 as IHarmonyQueryTable, new ExpressionValueComparer()); var tableList = flatList.Select(tpl => tpl.Item1 as IHarmonyQueryTable).ToList(); //extract all of expressions that might represent a given table and add them to the mapping dictionary foreach (var table in tableList) { foreach (var alias in ((HarmonyTableExpression)table).Aliases) { if (!expressionTableMapping.ContainsKey(alias)) { expressionTableMapping.Add(alias, table); } } } var whereBuilder = new WhereExpressionBuilder(rootExpr.IsCaseSensitive, tableList, expressionTableMapping); var processedWheres = new List <Object>(); var orderBys = new List <Tuple <FileIO.Queryable.FieldReference, bool> >(); foreach (var expr in rootExpr.WhereExpressions) { whereBuilder.VisitForWhere(expr, processedWheres, processedOns); } foreach (var tpl in flatList) { foreach (var expr in tpl.Item1.OnExpressions) { var madeOn = whereBuilder.VisitForOn(expr); if (madeOn != null) { processedOns.Add(madeOn); if (tpl.Item2.JoinOn == null) { tpl.Item2.JoinOn = madeOn; } else { throw new NotImplementedException(); } } } if (tpl.Item1 != rootExpr) { foreach (var expr in tpl.Item1.WhereExpressions) { var madeOn = whereBuilder.VisitForOn(expr); if (madeOn != null) { processedOns.Add(madeOn); if (tpl.Item2.JoinOn != null) { madeOn = new ConnectorPart() { Op = WhereClauseConnector.AndOperator, Left = tpl.Item2.JoinOn, Right = madeOn } } ; tpl.Item2.JoinOn = madeOn; } } } foreach (var expr in tpl.Item1.OrderByExpressions) { var fieldRef = whereBuilder.VisitForOrderBy(expr.Item1); if (fieldRef != null) { orderBys.Add(Tuple.Create(fieldRef, expr.Item2)); } } } var queryBuffer = new QueryBuffer(flatList.Select(tpl => tpl.Item2).ToList()); var fieldReferences = new Dictionary <int, List <FieldDataDefinition> >(); foreach (var queryExpr in flatList) { if (queryExpr.Item1.ReferencedFields.Count > 0) { var bufferIndex = queryBuffer.TypeBuffers.IndexOf(queryExpr.Item2); fieldReferences.Add(bufferIndex, queryExpr.Item1.ReferencedFields); } } var queryPlan = new PreparedQueryPlan(true, processedWheres, fieldReferences, processedOns, orderBys, queryBuffer, ""); return(queryPlan); }