public override Expression Apply(Expression expression, Random random) { var i = random.Next(_expressionFinder.FoundExpressions.Count); var expr = _expressionFinder.FoundExpressions[i]; var entityType = expr.Type.GetGenericArguments()[0]; var navigations = Context.Model.FindEntityType(entityType)?.GetNavigations().ToList(); var prm = Expression.Parameter(entityType, "prm"); if (navigations != null && navigations.Any()) { var j = random.Next(navigations.Count); var navigation = navigations[j]; var includeMethod = IncludeMethodInfo.MakeGenericMethod(entityType, navigation.ClrType); var injector = new ExpressionInjector( _expressionFinder.FoundExpressions[i], e => Expression.Call( includeMethod, e, Expression.Lambda(Expression.Property(prm, navigation.Name), prm))); return(injector.Visit(expression)); } return(expression); }
public override Expression Apply(Expression expression, Random random) { var i = random.Next(_expressionFinder.FoundExpressions.Count); var expr = _expressionFinder.FoundExpressions[i]; var thenInclude = random.Next(3) > 0; var entityType = expr.Type.GetGenericArguments()[0]; var propertyType = expr.Type.GetGenericArguments()[1]; var propertyElementType = IsEnumerableType(propertyType) || propertyType.GetInterfaces().Any(ii => IsEnumerableType(ii)) ? propertyType.GetGenericArguments()[0] : propertyType; var navigations = thenInclude ? Context.Model.FindEntityType(propertyElementType)?.GetNavigations().ToList() : Context.Model.FindEntityType(entityType)?.GetNavigations().ToList(); var prm = thenInclude ? Expression.Parameter(propertyElementType, "prm") : Expression.Parameter(entityType, "prm"); if (navigations != null && navigations.Any()) { var j = random.Next(navigations.Count); var navigation = navigations[j]; if (thenInclude) { var thenIncludeMethod = IsEnumerableType(propertyType) || propertyType.GetInterfaces().Any(ii => IsEnumerableType(ii)) ? ThenIncludeCollectionMethodInfo.MakeGenericMethod(entityType, propertyElementType, navigation.ClrType) : ThenIncludeReferenceMethodInfo.MakeGenericMethod(entityType, propertyElementType, navigation.ClrType); var injector = new ExpressionInjector( _expressionFinder.FoundExpressions[i], e => Expression.Call( thenIncludeMethod, e, Expression.Lambda(Expression.Property(prm, navigation.Name), prm))); return(injector.Visit(expression)); } else { var includeMethod = IncludeMethodInfo.MakeGenericMethod(entityType, navigation.ClrType); var injector = new ExpressionInjector( _expressionFinder.FoundExpressions[i], e => Expression.Call( includeMethod, e, Expression.Lambda(Expression.Property(prm, navigation.Name), prm))); return(injector.Visit(expression)); } } return(expression); }
// to get this to work, code was referenced and borrowed from https://github.com/aspnet/EntityFramework/blob/dev/src/EntityFramework.Core/EntityFrameworkQueryableExtensions.cs public static IQueryable <T> IncludeString <T>(this IQueryable <T> query, string include) where T : class, new() { // need to get the first include, and then append the thenincludes Type childType, parentType = typeof(T); MethodInfo includeMethodInfo; MethodInfo thenIncludeMethodInfo; MethodCallExpression methodCallExpression; IIncludableQueryable <T, object> resultQuery; string[] includeProperties = include.Split('.'); childType = parentType.GetProperty(includeProperties[0], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).PropertyType; includeMethodInfo = IncludeMethodInfo.MakeGenericMethod(parentType, childType); methodCallExpression = Expression.Call( includeMethodInfo, query.Expression, CreateExpression(parentType, includeProperties[0])); resultQuery = new IncludableQueryable <T, object>(query.Provider.CreateQuery <T>(methodCallExpression)); for (int i = 1; i < includeProperties.Length; i++) { parentType = childType; if (parentType.IsGenericType) { parentType = parentType.GetGenericArguments().First(); childType = parentType.GetProperty(includeProperties[i], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).PropertyType; thenIncludeMethodInfo = ThenIncludeAfterCollectionMethodInfo.MakeGenericMethod(typeof(T), parentType, childType); methodCallExpression = Expression.Call( thenIncludeMethodInfo, resultQuery.Expression, CreateExpression(parentType, includeProperties[i])); } resultQuery = new IncludableQueryable <T, object>(resultQuery.Provider.CreateQuery <T>(methodCallExpression)); } return(resultQuery); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void CompileIncludes( [NotNull] QueryModel queryModel, [NotNull] ICollection <IncludeResultOperator> includeResultOperators, bool trackingQuery) { var includeGroupings = CreateIncludeSpecifications(queryModel, includeResultOperators) .GroupBy(a => a.QuerySourceReferenceExpression); foreach (var includeGrouping in includeGroupings) { var entityParameter = Expression.Parameter(includeGrouping.Key.Type, name: "entity"); var propertyExpressions = new List <Expression>(); var blockExpressions = new List <Expression>(); if (trackingQuery) { blockExpressions.Add( Expression.Call( _queryBufferParameter, _startTrackingMethodInfo, entityParameter, Expression.Constant( _queryCompilationContext.Model .FindEntityType(entityParameter.Type)))); } var includedIndex = 0; foreach (var includeSpecification in includeGrouping) { _queryCompilationContext.Logger .LogDebug( CoreEventId.IncludingNavigation, () => CoreStrings.LogIncludingNavigation(includeSpecification.IncludeResultOperator)); propertyExpressions.AddRange( includeSpecification.NavigationPath .Select((t, i) => includeSpecification.NavigationPath .Take(i + 1) .Aggregate( (Expression)includeSpecification.QuerySourceReferenceExpression, EntityQueryModelVisitor.CreatePropertyExpression))); blockExpressions.Add( BuildIncludeExpressions( includeSpecification.NavigationPath, entityParameter, trackingQuery, ref includedIndex, navigationIndex: 0)); // TODO: Hack until new Include fully implemented includeResultOperators.Remove(includeSpecification.IncludeResultOperator); } var includeReplacingExpressionVisitor = new IncludeReplacingExpressionVisitor( includeGrouping.Key, Expression.Call( IncludeMethodInfo.MakeGenericMethod(includeGrouping.Key.Type), includeGrouping.Key, Expression.NewArrayInit( typeof(object), propertyExpressions), trackingQuery ? (Expression) Expression.Property( Expression.Property( EntityQueryModelVisitor.QueryContextParameter, propertyName: "StateManager"), propertyName: "Value") : Expression.Default(typeof(IStateManager)), trackingQuery ? (Expression) Expression.Property( EntityQueryModelVisitor.QueryContextParameter, propertyName: "QueryBuffer") : Expression.Default(typeof(IQueryBuffer)), Expression.Lambda( Expression.Block(typeof(void), blockExpressions), entityParameter, _includedParameter, _stateManagerParameter, _queryBufferParameter))); queryModel.SelectClause.TransformExpressions(includeReplacingExpressionVisitor.Visit); } }