示例#1
0
        internal static TypeUsage ValidateNewEntityWithRelationships(
            EntityType entityType,
            IEnumerable <DbExpression> attributeValues,
            IList <DbRelatedEntityRef> relationships,
            out DbExpressionList validArguments,
            out ReadOnlyCollection <DbRelatedEntityRef> validRelatedRefs)
        {
            TypeUsage typeUsage = ArgumentValidation.ValidateNew(ArgumentValidation.CreateResultType((EdmType)entityType), attributeValues, out validArguments);

            if (relationships.Count > 0)
            {
                List <DbRelatedEntityRef> relatedEntityRefList = new List <DbRelatedEntityRef>(relationships.Count);
                for (int index = 0; index < relationships.Count; ++index)
                {
                    DbRelatedEntityRef relationship = relationships[index];
                    EntityTypeBase     elementType  = TypeHelpers.GetEdmType <RefType>(relationship.SourceEnd.TypeUsage).ElementType;
                    if (!entityType.EdmEquals((MetadataItem)elementType) && !entityType.IsSubtypeOf((EdmType)elementType))
                    {
                        throw new ArgumentException(Strings.Cqt_NewInstance_IncompatibleRelatedEntity_SourceTypeNotValid, StringUtil.FormatIndex(nameof(relationships), index));
                    }
                    relatedEntityRefList.Add(relationship);
                }
                validRelatedRefs = new ReadOnlyCollection <DbRelatedEntityRef>((IList <DbRelatedEntityRef>)relatedEntityRefList);
            }
            else
            {
                validRelatedRefs = new ReadOnlyCollection <DbRelatedEntityRef>((IList <DbRelatedEntityRef>) new DbRelatedEntityRef[0]);
            }
            return(typeUsage);
        }
        private static DbRelatedEntityRef RelatedEntityRefFromAssociationSetEnd(EntityType constructedEntityType, DbNewInstanceExpression entityConstructor, AssociationSetEnd principalSetEnd, ReferentialConstraint fkConstraint)
        {
            EntityType           principalEntityType = (EntityType)TypeHelpers.GetEdmType <RefType>(fkConstraint.FromRole.TypeUsage).ElementType;
            IList <DbExpression> principalKeyValues  = null;

            // Create Entity Property/DbExpression value pairs from the entity constructor DbExpression,
            // then join these with the principal/dependent property pairs from the FK constraint
            // to produce principal property name/DbExpression value pairs from which to create the principal ref.
            //
            // Ideally the code would be as below, but anonymous types break asmmeta:
            //var keyPropAndValue =
            //    from pv in constructedEntityType.Properties.Select((p, idx) => new { DependentProperty = p, Value = entityConstructor.Arguments[idx] })
            //    join ft in fkConstraint.FromProperties.Select((fp, idx) => new { PrincipalProperty = fp, DependentProperty = fkConstraint.ToProperties[idx] })
            //    on pv.DependentProperty equals ft.DependentProperty
            //    select new { PrincipalProperty = ft.PrincipalProperty.Name, Value = pv.Value };
            //
            var keyPropAndValue =
                from pv in constructedEntityType.Properties.Select((p, idx) => Tuple.Create(p, entityConstructor.Arguments[idx])) // new { DependentProperty = p, Value = entityConstructor.Arguments[idx] })
                join ft in fkConstraint.FromProperties.Select((fp, idx) => Tuple.Create(fp, fkConstraint.ToProperties[idx]))      //new { PrincipalProperty = fp, DependentProperty = fkConstraint.ToProperties[idx] })
                on pv.Item1 equals ft.Item2                                                                                       //pv.DependentProperty equals ft.DependentProperty
                select Tuple.Create(ft.Item1.Name, pv.Item2);                                                                     // new { PrincipalProperty = ft.PrincipalProperty.Name, Value = pv.Value };

            // If there is only a single property in the principal's key, then there is no ordering concern.
            // Otherwise, create a dictionary of principal key property name to DbExpression value so that
            // when used as the arguments to the ref expression, the dependent property values - used here
            // as principal key property values - are in the correct order, which is the same order as the
            // key members themselves.
            //
            if (fkConstraint.FromProperties.Count == 1)
            {
                var singleKeyNameAndValue = keyPropAndValue.Single();
                Debug.Assert(singleKeyNameAndValue.Item1 == fkConstraint.FromProperties[0].Name, "Unexpected single key property name");
                principalKeyValues = new[] { singleKeyNameAndValue.Item2 };
            }
            else
            {
                var keyValueMap = keyPropAndValue.ToDictionary(pav => pav.Item1, pav => pav.Item2, StringComparer.Ordinal);
                principalKeyValues = principalEntityType.KeyMemberNames.Select(memberName => keyValueMap[memberName]).ToList();
            }

            // Create the ref to the principal entity based on the (now correctly ordered) key value expressions.
            //
            DbRefExpression    principalRef = principalSetEnd.EntitySet.CreateRef(principalEntityType, principalKeyValues);
            DbRelatedEntityRef result       = DbExpressionBuilder.CreateRelatedEntityRef(fkConstraint.ToRole, fkConstraint.FromRole, principalRef);

            return(result);
        }
 internal virtual void VisitRelatedEntityReference(DbRelatedEntityRef relatedEntityRef)
 {
     VisitExpression(relatedEntityRef.TargetEntityReference);
 }