/// <summary> /// Determines if the given property participating in any unique constraint for the specified entity. /// </summary> /// <param name="property">The property.</param> /// <param name="entityType">The entity type.</param> /// <returns>True if the given property participating in a unique constraint, false otherwise.</returns> public static bool IsUnique(this MemberProperty property, EntityType entityType) { ExceptionUtilities.CheckArgumentNotNull(property, "property"); ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); return(entityType.AllEdmUniqueConstraints.Any(c => c.Properties.Contains(property))); }
/// <summary> /// Determines if the given property is a foreign key in the specified entity set. /// </summary> /// <param name="property">The property.</param> /// <param name="entitySet">The entity set.</param> /// <returns>True if a given property is foreign key, false otherwise.</returns> public static bool IsForeignKey(this MemberProperty property, EntitySet entitySet) { ExceptionUtilities.CheckArgumentNotNull(property, "property"); ExceptionUtilities.CheckArgumentNotNull(entitySet, "entitySet"); ExceptionUtilities.CheckObjectNotNull(entitySet.Container, "The entity set '{0}' is not associated with an entity container.", entitySet.Name); return(entitySet.Container.AssociationSets.Any(a => a.AssociationType.ReferentialConstraint != null && a.AssociationType.ReferentialConstraint.DependentProperties.Contains(property) && entitySet == a.Ends.Single(e => e.AssociationEnd == a.AssociationType.ReferentialConstraint.DependentAssociationEnd).EntitySet)); }
/// <summary> /// Adds a property to the given type declaration based on the given metadata /// </summary> /// <param name="memberProperty">The property's metadata</param> /// <param name="parentClass">The type declaration</param> protected override void DeclareMemberProperty(MemberProperty memberProperty, CodeTypeDeclaration parentClass) { if (memberProperty.IsStream()) { this.DeclareNamedStreamProperty(memberProperty, parentClass); } else { this.AddPropertyWithChangeNotification(parentClass, this.GetPropertyType(memberProperty, CodeGenerationTypeUsage.Declaration), memberProperty.Name); } }
/// <summary> /// Performs a deep copy of the specified <see cref="MemberProperty"/>. /// </summary> /// <param name="memberProperty">The <see cref="MemberProperty"/> to deep copy.</param> /// <returns>A deep copy of the <see cref="MemberProperty"/>.</returns> private static MemberProperty Clone(this MemberProperty memberProperty) { var clone = new MemberProperty { Name = memberProperty.Name, PropertyType = memberProperty.PropertyType.Clone(), IsPrimaryKey = memberProperty.IsPrimaryKey, DefaultValue = memberProperty.DefaultValue, }; CopyAnnotations(clone, memberProperty.Annotations); return(clone); }
/// <summary> /// Improve the model if goal not yet met /// </summary> /// <param name="model">Model to improve</param> public void Fixup(EntityModelSchema model) { foreach (EntityType et in model.EntityTypes.Where(p => p.BaseType == null && p.AllKeyProperties.Count() == 0).ToList()) { if (et.Properties.Count() > 0) { et.Properties.First().IsPrimaryKey = true; } else { MemberProperty mp = new MemberProperty(); mp.IsPrimaryKey = true; et.Properties.Add(mp); } } }
/// <summary> /// Initializes a new instance of the PropertySegment class /// </summary> /// <param name="property">The property this segment corresponds to</param> internal PropertySegment(MemberProperty property) : base() { this.Property = property; if (property.PropertyType is ComplexDataType) { this.segmentType = ODataUriSegmentType.ComplexProperty; } else if (property.PropertyType is CollectionDataType) { this.segmentType = ODataUriSegmentType.MultiValueProperty; } else { this.segmentType = ODataUriSegmentType.PrimitiveProperty; } }
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; }
/// <summary> /// Visit member property to convert annotations /// </summary> /// <param name="memberProperty">member property to visit</param> protected override void VisitMemberProperty(MemberProperty memberProperty) { this.ConvertMimeTypeAnnotations(memberProperty); base.VisitMemberProperty(memberProperty); }
/// <summary> /// Generates the concurrency token attribute. /// </summary> /// <param name="memberProperty">The property.</param> /// <returns>Generated attribute</returns> protected override XAttribute GenerateStoreGeneratedPattern(MemberProperty memberProperty) { StoreGeneratedPatternAnnotation annotation = memberProperty.Annotations.OfType<StoreGeneratedPatternAnnotation>().SingleOrDefault(); if (annotation == null) { return null; } return new XAttribute(EdmConstants.AnnotationNamespace.GetName("StoreGeneratedPattern"), annotation.Name); }
/// <summary> /// Generates the concurrency token attribute. /// </summary> /// <param name="memberProperty">The property.</param> /// <returns>Generated attribute</returns> protected override XAttribute GenerateConcurrencyToken(MemberProperty memberProperty) { ConcurrencyTokenAnnotation annotation = memberProperty.Annotations.OfType<ConcurrencyTokenAnnotation>().SingleOrDefault(); if (annotation == null) { return null; } return new XAttribute("ConcurrencyMode", "Fixed"); }
private void GenerateNamedStreamAttribute(CodeTypeDeclaration entityTypeClass, MemberProperty streamProperty) { var epmAttribute = entityTypeClass.AddCustomAttribute(Code.TypeRef("NamedStream")); epmAttribute.Arguments.Add(new CodeAttributeArgument(Code.Primitive(streamProperty.Name))); }
/// <summary> /// Adds a named stream property to the given type declaration based on the given metadata /// </summary> /// <param name="namedStreamProperty">The named stream property's metadata</param> /// <param name="parentClass">The type declaration</param> protected virtual void DeclareNamedStreamProperty(MemberProperty namedStreamProperty, CodeTypeDeclaration parentClass) { }
/// <summary> /// Creates a QueryProperty for a property that is a non entity Collection /// </summary> /// <param name="library">Library Query Type</param> /// <param name="result">resulting Query Structural Type</param> /// <param name="collectionProperty">Member to calculate</param> /// <param name="pathToProperty">Path to the Property</param> /// <returns>A Query Property of the collectionType</returns> protected override QueryProperty CreateNonentityCollectionMember(QueryTypeLibrary library, QueryStructuralType result, MemberProperty collectionProperty, PathToProperty pathToProperty) { ExceptionUtilities.CheckArgumentNotNull(collectionProperty, "collectionProperty"); var collectionType = collectionProperty.PropertyType as CollectionDataType; ExceptionUtilities.Assert(collectionType != null, "This type of property is not supported."); var collectionPrimitiveElementType = collectionType.ElementDataType as PrimitiveDataType; var collectionComplexElementType = collectionType.ElementDataType as ComplexDataType; QueryCollectionType queryCollectionType = null; if (collectionPrimitiveElementType != null) { QueryScalarType queryPropertyType = this.GetQueryTypeForMappedProperty(pathToProperty, library, collectionPrimitiveElementType); queryCollectionType = queryPropertyType.CreateCollectionType(); } else { ExceptionUtilities.Assert(collectionComplexElementType != null, "This type of property is not supported."); QueryComplexType queryComplexType = this.CreateStubComplexType(collectionComplexElementType.Definition); CreateMembers(library, queryComplexType, collectionComplexElementType.Definition.Properties, pathToProperty); queryCollectionType = queryComplexType.CreateCollectionType(); } return QueryProperty.Create(collectionProperty.Name, queryCollectionType); }
private void PopulateCollectionPropertyWithNullOrEmpty(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues) { IEnumerable<NamedValue> exactMatches = namedValues.Where(nv => nv.Name == propertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", propertyPath); if (exactMatches.Count() == 1) { instance.Add(this.MultiValuePropertyEmptyOrNull(memberProperty, exactMatches.Single().Value)); } }
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> /// Sets the data generator for the given property and returns the property back. /// </summary> /// <param name="property">The property to set the data generator for.</param> /// <param name="dataGenerator">The data generator.</param> /// <returns>This instance (can be used to chain calls together).</returns> public static MemberProperty WithDataGenerator(this MemberProperty property, IDataGenerator dataGenerator) { ExceptionUtilities.CheckArgumentNotNull(property, "property"); return(property.WithDataGeneratorInternal(dataGenerator)); }
/// <summary> /// Adds data generation hints for the given property. /// </summary> /// <param name="property">Property to add data generation hints to.</param> /// <param name="hints">Data generation hints.</param> /// <returns>This instance (can be used to chain calls together).</returns> public static MemberProperty WithDataGenerationHints(this MemberProperty property, params DataGenerationHint[] hints) { ExceptionUtilities.CheckArgumentNotNull(property, "property"); return(property.WithDataGenerationHintsInternal(hints)); }
/// <summary> /// Returns the type to use when declaring or instantiating the property /// </summary> /// <param name="property">The property being declared/instantiated</param> /// <param name="usage">Whether the type is for declaration or instantiation</param> /// <returns>The type of the property</returns> protected CodeTypeReference GetPropertyType(MemberProperty property, CodeGenerationTypeUsage usage) { var collectionDataType = property.PropertyType as CollectionDataType; if (collectionDataType != null) { return this.GetCollectionType(usage, property.Annotations, collectionDataType.ElementDataType); } return this.BackingTypeResolver.ResolveClrTypeReference(property.PropertyType); }
/// <summary> /// Adds a property to the given type declaration based on the given metadata /// </summary> /// <param name="memberProperty">The property's metadata</param> /// <param name="parentClass">The type declaration</param> protected abstract void DeclareMemberProperty(MemberProperty memberProperty, CodeTypeDeclaration parentClass);
/// <summary> /// Initializes a new instance of the <see cref="PropertyWithConstraints"/> class. /// </summary> /// <param name="property">The property that has constraints.</param> public PropertyWithConstraints(MemberProperty property) { this.Property = property; this.constraints = new List<PropertyConstraint>(); }
/// <summary> /// Adds the specified property. /// </summary> /// <param name="property">The property to add.</param> public void Add(MemberProperty property) { this.Properties.Add(property); }
private static void AddDataGenerationHints(MemberProperty property, Type clrType) { DataGenerationHint[] hints; if (predefinedHintsPerType.TryGetValue(clrType, out hints)) { property.WithDataGenerationHints(hints); } }
/// <summary> /// Determines if the given property is store-generated. /// </summary> /// <param name="property">The property.</param> /// <returns>True if the given property is store-generated, false otherwise.</returns> public static bool IsStoreGenerated(this MemberProperty property) { ExceptionUtilities.CheckArgumentNotNull(property, "property"); return(property.Annotations.OfType <StoreGeneratedPatternAnnotation>().Any(a => a.ServerGeneratedOnInsert || a.ServerGeneratedOnUpdate)); }
/// <summary> /// Adds a property to the given type declaration based on the given metadata /// </summary> /// <param name="memberProperty">The property's metadata</param> /// <param name="parentClass">The type declaration</param> protected override void DeclareMemberProperty(MemberProperty memberProperty, CodeTypeDeclaration parentClass) { if (memberProperty.IsStream()) { this.DeclareNamedStreamProperty(memberProperty, parentClass); } else { parentClass.AddAutoImplementedProperty(this.GetPropertyType(memberProperty, CodeGenerationTypeUsage.Declaration), memberProperty.Name); } }
private void PopulatePrimitiveBagPropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues, PrimitiveDataType primitiveElementDataType) { int i = 0; bool completed = false; var primitiveCollection = new PrimitiveMultiValue(primitiveElementDataType.BuildMultiValueTypeName(), false); while (!completed) { IEnumerable<NamedValue> primitiveItemNamedValues = namedValues.Where(pp => pp.Name == propertyPath + "." + i).ToList(); if (primitiveItemNamedValues.Count() == 0) { completed = true; } else { ExceptionUtilities.Assert(primitiveItemNamedValues.Count() < 2, "Should not get more than one value for a primitive Bag item for path '{0}'", propertyPath + "." + i); var value = primitiveItemNamedValues.Single(); // Do something with the value primitiveCollection.Add(PrimitiveValue(primitiveElementDataType, value.Value)); } i++; } if (i > 1) { instance.Add(new PrimitiveMultiValueProperty(memberProperty.Name, primitiveCollection)); } }
/// <summary> /// Adds initialization for a property if any is needed /// </summary> /// <param name="memberProperty">The property to initialize</param> /// <param name="parentClassConstructor">The constructor to add to</param> protected virtual void DeclareOptionalPropertyInitializer(MemberProperty memberProperty, CodeConstructor parentClassConstructor) { // right now, we only need to initialize bag properties if (memberProperty.PropertyType is CollectionDataType) { var type = this.GetPropertyType(memberProperty, CodeGenerationTypeUsage.Instantiation); parentClassConstructor.Statements.Add(Code.This().Property(memberProperty.Name).Assign(Code.New(type))); } }
private Column ConvertPropertyToColumn(MemberProperty prop) { Column column = new Column(prop.Name, prop.PropertyType); if (prop.Annotations.OfType<StoreGeneratedPatternAnnotation>().Where(a => a == StoreGeneratedPatternAnnotation.Identity).Any()) { column.Annotations.Add(new IdentityColumnAnnotation()); } if (prop.Annotations.OfType<StoreGeneratedPatternAnnotation>().Where(a => a == StoreGeneratedPatternAnnotation.Computed).Any()) { column.Annotations.Add(new ComputedColumnAnnotation()); } return column; }
/// <summary> /// Parse a Property from its XElement /// </summary> /// <param name="propertyElement">XElement to parse Property from</param> /// <returns>A memberProperty</returns> protected virtual MemberProperty ParseProperty(XElement propertyElement) { var name = propertyElement.GetRequiredAttributeValue("Name"); DataType dataType = this.ParsePropertyDataType(propertyElement); var memberProperty = new MemberProperty(name, dataType); if (propertyElement.GetOptionalAttributeValue("ConcurrencyMode", "None") == "Fixed") { memberProperty.Annotations.Add(new ConcurrencyTokenAnnotation()); } this.ParseAnnotations(memberProperty, propertyElement); return memberProperty; }
/// <summary> /// Adds a new property to the type. /// </summary> /// <param name="property">Property to add</param> public void Add(MemberProperty property) { this.Properties.Add(property); }
/// <summary> /// Generates Property element for a given <see cref="MemberProperty"/> /// </summary> /// <param name="xmlNamespace">XML namespace to use</param> /// <param name="prop">Entity or ComplexType property</param> /// <returns>Property XElement</returns> protected override XElement GenerateProperty(XNamespace xmlNamespace, MemberProperty prop) { var element = base.GenerateProperty(xmlNamespace, prop); PropertyAccessModifierAnnotation accessModifierAnnotation = prop.Annotations.OfType<PropertyAccessModifierAnnotation>().SingleOrDefault(); if (accessModifierAnnotation != null) { element.Add(GeneratePropertyAccessModifier(accessModifierAnnotation)); } CollectionKindAnnotation collectionKindAnnotation = prop.Annotations.OfType<CollectionKindAnnotation>().SingleOrDefault(); if (collectionKindAnnotation != null) { element.Add(new XAttribute("CollectionKind", collectionKindAnnotation.CollectionKind.ToString())); } return element; }
private void PopulateComplexMultiValuePropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues, ComplexDataType complexTypeElementDataType) { int i = 0; bool completed = false; var complexCollection = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(complexTypeElementDataType.BuildMultiValueTypeName(), false)); while (!completed) { IEnumerable<NamedValue> complexInstanceNamedValues = namedValues.Where(pp => pp.Name.StartsWith(propertyPath + "." + i + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() == 0) { completed = true; } else { ComplexInstance complexInstance = this.ComplexInstance(complexTypeElementDataType.Definition, propertyPath + "." + i, complexInstanceNamedValues); complexCollection.Value.Add(complexInstance); } i++; } if (i > 1) { instance.Add(complexCollection); } }
private void CompareMemberProperty(MemberProperty expectedProperty, MemberProperty actualProperty) { this.CompareMemberPropertyDatatype(expectedProperty.Name, expectedProperty.PropertyType, actualProperty.PropertyType); this.WriteErrorIfFalse(expectedProperty.IsPrimaryKey == actualProperty.IsPrimaryKey, "Expected '{0}' for IsPrimaryKey of property '{1}' but got '{2}'", expectedProperty.IsPrimaryKey, expectedProperty.Name, actualProperty.IsPrimaryKey); ConcurrencyTokenAnnotation concurrencyToken = expectedProperty.Annotations.OfType<ConcurrencyTokenAnnotation>().FirstOrDefault(); if (concurrencyToken != null) { this.WriteErrorIfFalse(expectedProperty.Annotations.Any(), "Expected property '{0}' to have a concurrencyTokenAnnotation", expectedProperty.Name); } }
private MemberProperty ConvertToTaupoProperty(IEdmStructuralProperty edmProperty) { var taupoProperty = new MemberProperty(edmProperty.Name); taupoProperty.PropertyType = this.ConvertToTaupoDataType(edmProperty.Type); if (edmProperty.ConcurrencyMode == EdmConcurrencyMode.Fixed) { taupoProperty.Add(new ConcurrencyTokenAnnotation()); } if (!string.IsNullOrEmpty(edmProperty.DefaultValueString)) { taupoProperty.DefaultValue = edmProperty.DefaultValueString; } this.ConvertAnnotationsIntoTaupo(edmProperty, taupoProperty); return taupoProperty; }
private void Fixup(MemberProperty property) { property.PropertyType = this.replacementType.Nullable(property.PropertyType.IsNullable); }
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 void CompareMemberProperty(MemberProperty expectedProperty, MemberProperty actualProperty) { this.SatisfiesEquals(expectedProperty.Name, actualProperty.Name, "Property name does not match."); this.SatisfiesEquals(expectedProperty.IsPrimaryKey, actualProperty.IsPrimaryKey, "IsPrimaryKey of property '{0}' does not match.", expectedProperty.Name); this.CompareDataType(expectedProperty.PropertyType, actualProperty.PropertyType, "Property " + expectedProperty.Name); ConcurrencyTokenAnnotation expectedConcurrencyToken = expectedProperty.Annotations.OfType<ConcurrencyTokenAnnotation>().SingleOrDefault(); ConcurrencyTokenAnnotation actualConcurrencyToken = actualProperty.Annotations.OfType<ConcurrencyTokenAnnotation>().SingleOrDefault(); if (expectedConcurrencyToken != null) { this.SatisfiesCondition(actualConcurrencyToken != null, "Expected property '{0}' to be a concurrencyToken", expectedProperty.Name); } else { this.SatisfiesCondition(actualConcurrencyToken == null, "Expected property '{0}' to be NOT a concurrencyToken", expectedProperty.Name); } }
private void PopulateMultiValuePropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, DataType elementType, string propertyPath, IEnumerable<NamedValue> namedValues) { PrimitiveDataType primitiveElementDataType = elementType as PrimitiveDataType; ComplexDataType complexTypeElementDataType = elementType as ComplexDataType; if (primitiveElementDataType != null) { this.PopulatePrimitiveBagPropertyFromPaths(instance, memberProperty, propertyPath, namedValues, primitiveElementDataType); } else { ExceptionUtilities.CheckObjectNotNull(complexTypeElementDataType, "PropertyPath '{0}' is an invalid type '{1}'", propertyPath, memberProperty.PropertyType); this.PopulateComplexMultiValuePropertyFromPaths(instance, memberProperty, propertyPath, namedValues, complexTypeElementDataType); } }