private Expression CreateCollectionInitializer(LambdaScope lambdaScope, PropertyInfo collectionProperty, Type elementType, QueryLayer layer, LambdaScopeFactory lambdaScopeFactory) { MemberExpression propertyExpression = Expression.Property(lambdaScope.Accessor, collectionProperty); var builder = new QueryableBuilder(propertyExpression, elementType, typeof(Enumerable), _nameFactory, _resourceFactory, _resourceContextProvider, _entityModel, lambdaScopeFactory); Expression layerExpression = builder.ApplyQuery(layer); // Earlier versions of EF Core 3.x failed to understand `query.ToHashSet()`, so we emit `new HashSet(query)` instead. // Interestingly, EF Core 5 RC1 fails to understand `new HashSet(query)`, so we emit `query.ToHashSet()` instead. // https://github.com/dotnet/efcore/issues/22902 if (EntityFrameworkCoreSupport.Version.Major < 5) { Type enumerableOfElementType = typeof(IEnumerable <>).MakeGenericType(elementType); Type typedCollection = CollectionConverter.ToConcreteCollectionType(collectionProperty.PropertyType); ConstructorInfo typedCollectionConstructor = typedCollection.GetConstructor(enumerableOfElementType.AsArray()); if (typedCollectionConstructor == null) { throw new InvalidOperationException($"Constructor on '{typedCollection.Name}' that accepts '{enumerableOfElementType.Name}' not found."); } return(Expression.New(typedCollectionConstructor, layerExpression)); } string operationName = CollectionConverter.TypeCanContainHashSet(collectionProperty.PropertyType) ? "ToHashSet" : "ToList"; return(CopyCollectionExtensionMethodCall(layerExpression, operationName, elementType)); }
public override Expression VisitCollectionNotEmpty(CollectionNotEmptyExpression expression, Type argument) { Expression property = Visit(expression.TargetCollection, argument); Type elementType = CollectionConverter.TryGetCollectionElementType(property.Type); if (elementType == null) { throw new InvalidOperationException("Expression must be a collection."); } Expression predicate = null; if (expression.Filter != null) { var hasManyThrough = expression.TargetCollection.Fields.Last() as HasManyThroughAttribute; var lambdaScopeFactory = new LambdaScopeFactory(_nameFactory, hasManyThrough); using LambdaScope lambdaScope = lambdaScopeFactory.CreateScope(elementType); var builder = new WhereClauseBuilder(property, lambdaScope, typeof(Enumerable), _nameFactory); predicate = builder.GetPredicateLambda(expression.Filter); } return(AnyExtensionMethodCall(elementType, property, predicate)); }
public QueryableBuilder(Expression source, Type elementType, Type extensionType, LambdaParameterNameFactory nameFactory, IResourceFactory resourceFactory, IResourceContextProvider resourceContextProvider, IModel entityModel, LambdaScopeFactory lambdaScopeFactory = null) { _source = source ?? throw new ArgumentNullException(nameof(source)); _elementType = elementType ?? throw new ArgumentNullException(nameof(elementType)); _extensionType = extensionType ?? throw new ArgumentNullException(nameof(extensionType)); _nameFactory = nameFactory ?? throw new ArgumentNullException(nameof(nameFactory)); _resourceFactory = resourceFactory ?? throw new ArgumentNullException(nameof(resourceFactory)); _resourceContextProvider = resourceContextProvider ?? throw new ArgumentNullException(nameof(resourceContextProvider)); _entityModel = entityModel ?? throw new ArgumentNullException(nameof(entityModel)); _lambdaScopeFactory = lambdaScopeFactory ?? new LambdaScopeFactory(_nameFactory); }
private MemberAssignment CreatePropertyAssignment(PropertySelector selector, LambdaScope lambdaScope) { MemberExpression propertyAccess = Expression.Property(lambdaScope.Accessor, selector.Property); Expression assignmentRightHandSide = propertyAccess; if (selector.NextLayer != null) { HasManyThroughAttribute hasManyThrough = selector.OriginatingField as HasManyThroughAttribute; var lambdaScopeFactory = new LambdaScopeFactory(_nameFactory, hasManyThrough); assignmentRightHandSide = CreateAssignmentRightHandSideForLayer(selector.NextLayer, lambdaScope, propertyAccess, selector.Property, lambdaScopeFactory); } return(Expression.Bind(selector.Property, assignmentRightHandSide)); }
public QueryableBuilder(Expression source, Type elementType, Type extensionType, LambdaParameterNameFactory nameFactory, IResourceFactory resourceFactory, IResourceContextProvider resourceContextProvider, IModel entityModel, LambdaScopeFactory lambdaScopeFactory = null) { ArgumentGuard.NotNull(source, nameof(source)); ArgumentGuard.NotNull(elementType, nameof(elementType)); ArgumentGuard.NotNull(extensionType, nameof(extensionType)); ArgumentGuard.NotNull(nameFactory, nameof(nameFactory)); ArgumentGuard.NotNull(resourceFactory, nameof(resourceFactory)); ArgumentGuard.NotNull(resourceContextProvider, nameof(resourceContextProvider)); ArgumentGuard.NotNull(entityModel, nameof(entityModel)); _source = source; _elementType = elementType; _extensionType = extensionType; _nameFactory = nameFactory; _resourceFactory = resourceFactory; _resourceContextProvider = resourceContextProvider; _entityModel = entityModel; _lambdaScopeFactory = lambdaScopeFactory ?? new LambdaScopeFactory(_nameFactory); }
private Expression CreateCollectionInitializer(LambdaScope lambdaScope, PropertyInfo collectionProperty, Type elementType, QueryLayer layer, LambdaScopeFactory lambdaScopeFactory) { MemberExpression propertyExpression = Expression.Property(lambdaScope.Accessor, collectionProperty); var builder = new QueryableBuilder(propertyExpression, elementType, typeof(Enumerable), _nameFactory, _resourceFactory, _resourceContextProvider, _entityModel, lambdaScopeFactory); Expression layerExpression = builder.ApplyQuery(layer); Type enumerableOfElementType = typeof(IEnumerable <>).MakeGenericType(elementType); Type typedCollection = TypeHelper.ToConcreteCollectionType(collectionProperty.PropertyType); ConstructorInfo typedCollectionConstructor = typedCollection.GetConstructor(new[] { enumerableOfElementType }); if (typedCollectionConstructor == null) { throw new Exception( $"Constructor on '{typedCollection.Name}' that accepts '{enumerableOfElementType.Name}' not found."); } return(Expression.New(typedCollectionConstructor, layerExpression)); }
private Expression CreateAssignmentRightHandSideForLayer(QueryLayer layer, LambdaScope outerLambdaScope, MemberExpression propertyAccess, PropertyInfo selectorPropertyInfo, LambdaScopeFactory lambdaScopeFactory) { Type collectionElementType = TypeHelper.TryGetCollectionElementType(selectorPropertyInfo.PropertyType); Type bodyElementType = collectionElementType ?? selectorPropertyInfo.PropertyType; if (collectionElementType != null) { return(CreateCollectionInitializer(outerLambdaScope, selectorPropertyInfo, bodyElementType, layer, lambdaScopeFactory)); } if (layer.Projection == null || !layer.Projection.Any()) { return(propertyAccess); } using var scope = lambdaScopeFactory.CreateScope(bodyElementType, propertyAccess); return(CreateLambdaBodyInitializer(layer.Projection, layer.ResourceContext, scope, true)); }