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); }