/// <summary> /// Extends value population to include stream data /// </summary> /// <param name="row">The row containing the data</param> /// <param name="instance">The structural instacne</param> protected override void PopulateInstanceFromRow(EntitySetDataRow row, QueryStructuralValue instance) { base.PopulateInstanceFromRow(row, instance); var rowWithStreams = row as EntitySetDataRowWithStreams; if (rowWithStreams != null) { foreach (var stream in rowWithStreams.Streams) { if (stream.IsEditLinkBasedOnConvention) { ExceptionUtilities.CheckObjectNotNull(this.LinkGenerator, "Cannot compute convention-based edit link without injected generator"); stream.EditLink = this.LinkGenerator.GenerateStreamEditLink(instance, stream.Name); // for the default stream, there must always be a self-link if (stream.Name == null && stream.SelfLink == null) { stream.SelfLink = stream.EditLink; } } instance.SetStreamValue(stream.Name, stream.ContentType, stream.ETag, stream.EditLink, stream.SelfLink, stream.Content); } } instance.MarkDynamicPropertyValues(); }
private void PopulateNavigations(EntitySetDataRow row, QueryStructuralValue instance) { var entityInstance = instance as QueryEntityValue; EntitySetData entitySetData = row.Parent; EntityContainerData containerData = entitySetData.Parent; foreach (AssociationSet associationSet in containerData.EntityContainer.AssociationSets) { foreach (var fromSetEnd in associationSet.Ends.Where(e => e.EntitySet == entitySetData.EntitySet)) { var fromEntityType = fromSetEnd.AssociationEnd.EntityType; if (!row.EntityType.IsKindOf(fromEntityType)) { continue; } var toSetEnd = associationSet.GetOtherEnd(fromSetEnd); this.PopulateNavigateResult(row, entityInstance, associationSet, fromSetEnd, toSetEnd); // if Navigation property exists, populate it as well var navProp = row.EntityType.AllNavigationProperties.SingleOrDefault(p => p.Association == associationSet.AssociationType && p.ToAssociationEnd == toSetEnd.AssociationEnd); if (navProp != null) { instance.SetValue(navProp.Name, entityInstance.GetNavigateResult(navProp.Association, navProp.ToAssociationEnd)); } } } }
private void ConsiderCandidateForRelationships(EntitySetDataRow row) { foreach (RelationshipSelector rs in this.relationshipSelectors) { rs.ConsiderCandidate(row.Parent.EntitySet, row.EntityType, row.Key); } }
private void CreateRelationships( EntityContainerData data, ref int createdEntitiesCount, ref int createdAssociationsCount) { List <RelationshipDescription> relationshipsToCreate; List <KeyValuePair <EntitySet, EntityType> > entitiesToCreateInCurrentBatch; int loopCount = 0; while (this.GetRelationshipsAndEntitiesToCreate(out relationshipsToCreate, out entitiesToCreateInCurrentBatch)) { loopCount++; // there are times when relationships are unable to be created for particular entity type graphs // in these situations this check guards against running infinitely long, adding 20 // ensures that all models get at least 100 loops to generate relationship data, otherwise this // guard might be too low if (loopCount > ((this.relationshipSelectors.Count * 4) + 20)) { throw new TaupoInvalidOperationException("Specified relationship requirements cannot be met. Make sure capacity selectors don't contradict each other."); } this.PopulateAssociationSetRows(data, relationshipsToCreate); createdAssociationsCount += relationshipsToCreate.Count; foreach (var setTypePair in entitiesToCreateInCurrentBatch) { EntitySetDataRow r = this.PopulateNewEntitySetRow(data, setTypePair.Key, setTypePair.Value); createdEntitiesCount++; this.ConsiderCandidateForRelationships(r); } } }
private void ResolveConstraints(EntitySetDataRow row, PropertyWithConstraints propertyWithConstraints) { List <PropertyConstraint> constraints = propertyWithConstraints.GetConstraints(row.EntityType); if (constraints.Count > 0) { this.ResolvePropertyValue(row, propertyWithConstraints.Property, constraints); } }
private IEntitySetData CreateObjectFromRow(EntitySetDataRow targetRow) { var targetEntityType = targetRow.EntityType; var targetObject = this.ObjectServices.GetObjectAdapter(targetEntityType.FullName).CreateData( targetRow.PropertyPaths.Select(p => new NamedValue(p, targetRow.GetValue(p))).Where(v => v.Value != UninitializedData.Value)); return(this.CreateEntitySetObjectData(targetObject, targetRow.Parent.EntitySet.ContainerQualifiedName)); }
private object ResolvePropertyValue(EntitySetDataRow row, MemberProperty property, List <PropertyConstraint> constraints) { if (this.resolved.Any(kv => kv.Key == row && kv.Value == property)) { return(row[property.Name]); } KeyValuePair <EntitySetDataRow, MemberProperty> sameItem = this.visited.Where(kv => kv.Key == row && kv.Value == property).SingleOrDefault(); if (sameItem.Key != null) { int indexCycleStartsWith = this.visited.IndexOf(sameItem); List <object> values = this.visited.Where((kv, i) => i >= indexCycleStartsWith).Select(kv => kv.Key[kv.Value.Name]).Distinct(ValueComparer.Instance).ToList(); if (values.Count > 1) { throw new TaupoInvalidOperationException("Referential constraint cycle detected: " + GetReferentialConstraintCycleDescription(this.visited, indexCycleStartsWith)); } return(values[0]); } var candidates = new List <object>(); foreach (PropertyConstraint constraint in constraints) { object candidate; if (this.ResolveConstraintValue(row, property, constraint, out candidate)) { candidates.Add(candidate); } } if (candidates.Distinct(ValueComparer.Instance).Count() > 1) { throw new TaupoInvalidOperationException("Overlapping foreign keys with conflicting values detected: " + GetOverlappingForeignKeyDescription(constraints)); } object value; if (candidates.Count > 0) { value = candidates[0]; if (!ValueComparer.Instance.Equals(value, row[property.Name])) { row[property.Name] = value; } } else { value = row[property.Name]; } this.resolved.Add(new KeyValuePair <EntitySetDataRow, MemberProperty>(row, property)); return(value); }
private EntitySetDataRow PopulateEntitySetRow(EntityContainerData data, EntitySet entitySet, EntityType entityType, IEnumerable <NamedValue> entityData) { EntitySetDataRow row = data[entitySet].AddNewRowOfType(entityType); foreach (NamedValue namedValue in entityData) { row.SetValue(namedValue.Name, namedValue.Value); } this.entitySetAndTypeSelector.IncrementCount(entitySet, entityType); return(row); }
private void PopulateNavigateResult(EntitySetDataRow row, QueryEntityValue entityInstance, AssociationSet associationSet, AssociationSetEnd fromSetEnd, AssociationSetEnd toSetEnd) { EntityContainerData containerData = row.Parent.Parent; var associationSetData = containerData.GetAssociationSetData(associationSet.Name); var targetInstanceLookup = this.rowInstances[toSetEnd.EntitySet.Name]; var associatedObjects = associationSetData.Rows .Where(r => r.GetRoleKey(fromSetEnd.AssociationEnd.RoleName).Equals(row.Key)) .Select(r => targetInstanceLookup[r.GetRoleKey(toSetEnd.AssociationEnd.RoleName)]) .ToArray(); var toEntityType = toSetEnd.AssociationEnd.EntityType; var toQueryEntityType = this.GetQueryType(toSetEnd.EntitySet.Name, toEntityType); if (toSetEnd.AssociationEnd.Multiplicity == EndMultiplicity.Many) { var collectionType = toQueryEntityType.CreateCollectionType(); var collectionValue = collectionType.CreateCollectionWithValues(associatedObjects); entityInstance.SetNavigateResult(associationSet.AssociationType, toSetEnd.AssociationEnd, collectionValue); } else { if (associatedObjects.Length == 0) { entityInstance.SetNavigateResult(associationSet.AssociationType, toSetEnd.AssociationEnd, toQueryEntityType.NullValue); } else { if (associatedObjects.Length != 1) { var debugAssociatedValues = string.Join("," + Environment.NewLine, associatedObjects.Select(ao => ao.ToString())); throw new TaupoInfrastructureException( string.Format( CultureInfo.InvariantCulture, "Found {0} associated objects for {1}.{2}, on Entity Instance {3} associated Objects = {4}", associatedObjects.Length, associationSet.AssociationType.FullName, fromSetEnd.AssociationEnd.RoleName, entityInstance, debugAssociatedValues)); } var targetInstance = associatedObjects.Single(); entityInstance.SetNavigateResult(associationSet.AssociationType, toSetEnd.AssociationEnd, targetInstance); } } }
private bool ResolveConstraintValue(EntitySetDataRow dependentRow, MemberProperty property, PropertyConstraint constraint, out object value) { value = null; List <AssociationSetDataRow> associationRows = this.data[constraint.AssociationSet].Rows.Where( r => ReferenceEquals(r.GetRoleKey(constraint.DependentRoleName), dependentRow.Key)).ToList(); if (associationRows.Count == 0) { return(false); } if (associationRows.Count > 1) { throw new TaupoInvalidOperationException(string.Format( CultureInfo.InvariantCulture, "Multiplicity constraint violated: the association set '{0}' has multiple rows with the same role key for the dependent role '{1}'.", constraint.AssociationSet.Name, constraint.DependentRoleName)); } EntityDataKey principalKey = associationRows[0].GetRoleKey(constraint.PrincipalRoleName); EntitySetDataRow principalRow = this.data[constraint.PrincipalEntitySet].Rows.Where(r => ReferenceEquals(r.Key, principalKey)).SingleOrDefault(); if (principalRow != null) { List <PropertyConstraint> constraints; if (this.TryGetConstraints(principalRow, constraint.PrincipalProperty, out constraints)) { var item = new KeyValuePair <EntitySetDataRow, MemberProperty>(dependentRow, property); this.visited.Add(item); value = this.ResolvePropertyValue(principalRow, constraint.PrincipalProperty, constraints); this.visited.Remove(item); } else { value = principalRow[constraint.PrincipalProperty.Name]; } } else if (constraint.PrincipalProperty.IsPrimaryKey) { value = principalKey[constraint.PrincipalProperty.Name]; } return(true); }
/// <summary> /// Tries to get next data to upload. /// </summary> /// <param name="data">The data to upload.</param> /// <returns>True if there is a data for upload, false otherwise.</returns> public virtual bool TryPopulateNextData(out EntityContainerData data) { ExceptionUtilities.CheckObjectNotNull(this.StructuralDataServices, "StructuralGenerators cannot be null."); this.CreateEntitySetAndTypeSelectorIfNull(); this.CreateRelationshipSelectorsIfNull(); if (this.seedData != null) { data = this.seedData; this.seedData = null; } else { data = new EntityContainerData(this.EntityContainer); } int createdEntitiesCount = 0, createdAssociationsCount = 0; this.CreateRelationships(data, ref createdEntitiesCount, ref createdAssociationsCount); EntitySet entitySet; EntityType entityType; while (this.GetNextEntitySetAndTypeToCreate(out entitySet, out entityType)) { EntitySetDataRow row = this.PopulateNewEntitySetRow(data, entitySet, entityType); createdEntitiesCount++; this.ConsiderCandidateForRelationships(row); this.CreateRelationships(data, ref createdEntitiesCount, ref createdAssociationsCount); if (createdEntitiesCount >= this.ThresholdForNumberOfEntities && this.ThresholdForNumberOfEntities != -1) { break; } } if (this.ReferentialConstraintsResolver != null) { this.ReferentialConstraintsResolver.ResolveReferentialConstraints(data); } return(createdEntitiesCount > 0 || createdAssociationsCount > 0); }
private void PopulateScalarAndComplexCollectionAndNonCollectionProperties(EntitySetDataRow row, QueryStructuralValue instance) { IEnumerable <QueryProperty> allProperties = instance.Type.Properties; if (instance.Type is QueryEntityType) { List <string> properties = ((QueryEntityType)instance.Type).EntityType.AllProperties.Select(p => p.Name).ToList(); allProperties = instance.Type.Properties.Where(m => properties.Contains(m.Name)); } List <QueryProperty> nonEntityQueryProperties = new List <QueryProperty>(); foreach (QueryProperty qp in allProperties) { nonEntityQueryProperties.Add(qp); } this.BuildStructuralPropertiesQueryValue(instance, string.Empty, row.EntityType.AllProperties.ToList(), nonEntityQueryProperties, row); }
private bool TryGetConstraints(EntitySetDataRow row, MemberProperty property, out List <PropertyConstraint> constraints) { constraints = null; List <PropertyWithConstraints> propertiesWithConstraints; if (this.entitySetToConstraintsMap.TryGetValue(row.Parent.EntitySet, out propertiesWithConstraints)) { constraints = propertiesWithConstraints .Where(p => p.Property == property) .Select(p => p.GetConstraints(row.EntityType)).SingleOrDefault(); if (constraints != null && constraints.Count == 0) { constraints = null; } } return(constraints != null); }
private void BuildStructuralPropertiesQueryValue(QueryStructuralValue instance, string propertyPath, IList <MemberProperty> properties, IList <QueryProperty> queryProperties, EntitySetDataRow row) { ExceptionUtilities.Assert(properties.Count == queryProperties.Count, "QueryProperties '{0}' and MemberProperties '{1}' are not the same number!", CreateQueryPropertyList(queryProperties), CreateMemberPropertyList(properties)); // TODO: Some Taupo framework pieces skip over StreamDataType properties foreach (MemberProperty childProperty in properties.Where(p => !(p.PropertyType is StreamDataType))) { string childPropertyPath = propertyPath + childProperty.Name; List <QueryProperty> childQueryProperties = queryProperties.Where(p => p.Name == childProperty.Name).ToList(); ExceptionUtilities.Assert(childQueryProperties.Count == 1, "Could not find query property based on MemberProperty Name '{0}' in list of query properties '{1}'", childProperty.Name, CreateQueryPropertyList(childQueryProperties)); QueryProperty childQueryProperty = childQueryProperties.First(); QueryCollectionType childCollectionDataType = childQueryProperty.PropertyType as QueryCollectionType; QueryScalarType childScalarType = childQueryProperty.PropertyType as QueryScalarType; QueryComplexType childComplexType = childQueryProperty.PropertyType as QueryComplexType; if (childCollectionDataType != null) { instance.SetValue(childProperty.Name, this.BuildCollectionQueryValue(childPropertyPath + ".", childCollectionDataType, row)); } else if (childScalarType != null) { var value = row[childPropertyPath]; var queryValue = childScalarType.CreateValue(value); instance.SetValue(childQueryProperty.Name, queryValue); } else { ExceptionUtilities.CheckObjectNotNull(childComplexType, "Unknown type '{0}'", childProperty.PropertyType); // If a complex type instance is null in the datarow, we will create a QueryStructuralValue indicating null and set it on the instance. if (row.PropertyPaths.Contains(childPropertyPath) && row[childPropertyPath] == null) { instance.SetValue(childProperty.Name, new QueryStructuralValue(childComplexType, true, null, childComplexType.EvaluationStrategy)); } else { QueryStructuralValue childInstance = childComplexType.CreateNewInstance(); this.BuildStructuralPropertiesQueryValue(childInstance, childPropertyPath + ".", childComplexType.ComplexType.Properties, childComplexType.Properties, row); instance.SetValue(childProperty.Name, childInstance); } } } }
private QueryValue BuildCollectionQueryValue(string propertyPath, QueryCollectionType queryCollectionType, EntitySetDataRow row) { QueryScalarType scalarElementDataType = queryCollectionType.ElementType as QueryScalarType; QueryComplexType complexTypeElementDataType = queryCollectionType.ElementType as QueryComplexType; List <QueryValue> queryValues = new List <QueryValue>(); if (scalarElementDataType != null) { int i = 0; while (row.PropertyPaths.Any(pp => pp == propertyPath + i)) { var value = row[propertyPath + i]; queryValues.Add(scalarElementDataType.CreateValue(value)); i++; } } else { ExceptionUtilities.CheckObjectNotNull(complexTypeElementDataType, "PropertyPath '{0}' is an invalid type '{1}'", propertyPath, queryCollectionType.ElementType); int i = 0; while (row.PropertyPaths.Where(pp => pp.StartsWith(propertyPath + i, StringComparison.Ordinal)).Count() > 0) { QueryStructuralValue complexChildInstance = complexTypeElementDataType.CreateNewInstance(); this.BuildStructuralPropertiesQueryValue(complexChildInstance, propertyPath + i + ".", complexTypeElementDataType.ComplexType.Properties, complexTypeElementDataType.Properties, row); queryValues.Add(complexChildInstance); i++; } } return(queryCollectionType.CreateCollectionWithValues(queryValues.ToArray())); }
/// <summary> /// Helper method for populating property values on the given instance /// </summary> /// <param name="row">The row containing the data</param> /// <param name="instance">The structural instacne</param> protected virtual void PopulateInstanceFromRow(EntitySetDataRow row, QueryStructuralValue instance) { this.PopulateNavigations(row, instance); this.PopulateScalarAndComplexCollectionAndNonCollectionProperties(row, instance); }