Exemplo n.º 1
0
        public LambdaScopeFactory(LambdaParameterNameFactory nameFactory, HasManyThroughAttribute hasManyThrough = null)
        {
            ArgumentGuard.NotNull(nameFactory, nameof(nameFactory));

            _nameFactory    = nameFactory;
            _hasManyThrough = hasManyThrough;
        }
Exemplo n.º 2
0
        /// <inheritdoc />
        public QueryLayer ComposeForHasManyThrough <TId>(HasManyThroughAttribute hasManyThroughRelationship, TId leftId, ICollection <IIdentifiable> rightResourceIds)
        {
            var leftResourceContext = _resourceContextProvider.GetResourceContext(hasManyThroughRelationship.LeftType);
            var leftIdAttribute     = GetIdAttribute(leftResourceContext);

            var rightResourceContext = _resourceContextProvider.GetResourceContext(hasManyThroughRelationship.RightType);
            var rightIdAttribute     = GetIdAttribute(rightResourceContext);
            var rightTypedIds        = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray();

            var leftFilter  = CreateFilterByIds(new[] { leftId }, leftIdAttribute, null);
            var rightFilter = CreateFilterByIds(rightTypedIds, rightIdAttribute, null);

            return(new QueryLayer(leftResourceContext)
            {
                Include = new IncludeExpression(new[] { new IncludeElementExpression(hasManyThroughRelationship) }),
                Filter = leftFilter,
                Projection = new Dictionary <ResourceFieldAttribute, QueryLayer>
                {
                    [hasManyThroughRelationship] = new QueryLayer(rightResourceContext)
                    {
                        Filter = rightFilter,
                        Projection = new Dictionary <ResourceFieldAttribute, QueryLayer>
                        {
                            [rightIdAttribute] = null
                        }
                    },
                    [leftIdAttribute] = null
                }
            });
        }
Exemplo n.º 3
0
        public LambdaScope(LambdaParameterNameFactory nameFactory, Type elementType, Expression accessorExpression, HasManyThroughAttribute hasManyThrough)
        {
            if (nameFactory == null)
            {
                throw new ArgumentNullException(nameof(nameFactory));
            }
            if (elementType == null)
            {
                throw new ArgumentNullException(nameof(elementType));
            }

            _parameterNameScope = nameFactory.Create(elementType.Name);
            Parameter           = Expression.Parameter(elementType, _parameterNameScope.Name);

            if (accessorExpression != null)
            {
                Accessor = accessorExpression;
            }
            else if (hasManyThrough != null)
            {
                Accessor = Expression.Property(Parameter, hasManyThrough.RightProperty);
            }
            else
            {
                Accessor = Parameter;
            }

            HasManyThrough = hasManyThrough;
        }
Exemplo n.º 4
0
 private IEnumerable <IIdentifiable> GetHasManyThroughIter(HasManyThroughAttribute hasManyThrough, IEnumerable hasManyNavigationEntity)
 {
     foreach (var includedEntity in hasManyNavigationEntity)
     {
         var targetValue = hasManyThrough.RightProperty.GetValue(includedEntity) as IIdentifiable;
         yield return(targetValue);
     }
 }
Exemplo n.º 5
0
        private IEnumerable <IIdentifiable> GetHasManyThrough(IIdentifiable parent, HasManyThroughAttribute hasManyThrough)
        {
            var throughProperty = GetRelationship(parent, hasManyThrough.InternalThroughName);

            if (throughProperty is IEnumerable hasManyNavigationEntity)
            {
                // wrap "yield return" in a sub-function so we can correctly return null if the property is null.
                return(GetHasManyThroughIter(hasManyThrough, hasManyNavigationEntity));
            }
            return(null);
        }
Exemplo n.º 6
0
        private IEnumerable <IIdentifiable> GetHasManyThrough(IIdentifiable parent, HasManyThroughAttribute hasManyThrough)
        {
            var throughProperty = GetRelationship(parent, hasManyThrough.InternalThroughName);

            if (throughProperty is IEnumerable hasManyNavigationEntity)
            {
                foreach (var includedEntity in hasManyNavigationEntity)
                {
                    var targetValue = hasManyThrough.RightProperty.GetValue(includedEntity) as IIdentifiable;
                    yield return(targetValue);
                }
            }
        }
        private async Task RemoveExistingIdsFromSecondarySet(TId primaryId, ISet <IIdentifiable> secondaryResourceIds,
                                                             HasManyThroughAttribute hasManyThrough, CancellationToken cancellationToken)
        {
            var queryLayer       = _queryLayerComposer.ComposeForHasMany(hasManyThrough, primaryId, secondaryResourceIds);
            var primaryResources = await _repositoryAccessor.GetAsync <TResource>(queryLayer, cancellationToken);

            var primaryResource = primaryResources.FirstOrDefault();

            AssertPrimaryResourceExists(primaryResource);

            var rightValue = _request.Relationship.GetValue(primaryResource);
            var existingRightResourceIds = TypeHelper.ExtractResources(rightValue);

            secondaryResourceIds.ExceptWith(existingRightResourceIds);
        }
        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));
        }
Exemplo n.º 9
0
        private async Task UpdateManyToManyAsync(IIdentifiable parent, HasManyThroughAttribute relationship, IEnumerable <string> relationshipIds)
        {
            // we need to create a transaction for the HasManyThrough case so we can get and remove any existing
            // join entities and only commit if all operations are successful
            var transaction = await _context.GetCurrentOrCreateTransactionAsync();

            // ArticleTag
            ParameterExpression parameter = Expression.Parameter(relationship.ThroughType);
            // ArticleTag.ArticleId
            Expression idMember = Expression.Property(parameter, relationship.LeftIdProperty);
            // article.Id
            var        parentId = TypeHelper.ConvertType(parent.StringId, relationship.LeftIdProperty.PropertyType);
            Expression target   = Expression.Constant(parentId);
            // ArticleTag.ArticleId.Equals(article.Id)
            Expression callEquals = Expression.Call(idMember, "Equals", null, target);
            var        lambda     = Expression.Lambda <Func <TRelatedResource, bool> >(callEquals, parameter);
            // TODO: we shouldn't need to do this instead we should try updating the existing?
            // the challenge here is if a composite key is used, then we will fail to
            // create due to a unique key violation
            var oldLinks = _context
                           .Set <TRelatedResource>()
                           .Where(lambda.Compile())
                           .ToList();

            _context.RemoveRange(oldLinks);

            var newLinks = relationshipIds.Select(x =>
            {
                var link = Activator.CreateInstance(relationship.ThroughType);
                relationship.LeftIdProperty.SetValue(link, TypeHelper.ConvertType(parentId, relationship.LeftIdProperty.PropertyType));
                relationship.RightIdProperty.SetValue(link, TypeHelper.ConvertType(x, relationship.RightIdProperty.PropertyType));
                return(link);
            });

            _context.AddRange(newLinks);
            await _context.SaveChangesAsync();

            transaction.Commit();
        }
Exemplo n.º 10
0
 public LambdaScopeFactory(LambdaParameterNameFactory nameFactory, HasManyThroughAttribute hasManyThrough = null)
 {
     _nameFactory    = nameFactory ?? throw new ArgumentNullException(nameof(nameFactory));
     _hasManyThrough = hasManyThrough;
 }