/// <summary> /// Fixes up the two navigation properties refered to by a resource association set /// </summary> /// <param name="resourceAssociationSet">Resource association set to inspect.</param> private void PairUpNavigationPropertyWithResourceAssociationSet(ResourceAssociationSet resourceAssociationSet) { bool isBiDirectional = resourceAssociationSet.End1.ResourceProperty != null && resourceAssociationSet.End2.ResourceProperty != null && resourceAssociationSet.End1.ResourceProperty != resourceAssociationSet.End2.ResourceProperty; string end1Name; EdmMultiplicity navigationProperty1Multiplicity; EdmOnDeleteAction end1DeleteAction; string end2Name; EdmMultiplicity navigationProperty2Multiplicity; EdmOnDeleteAction end2DeleteAction; bool end1IsPrinciple = false; List<IEdmStructuralProperty> dependentProperties = null; ResourceAssociationType resourceAssociationType = resourceAssociationSet.ResourceAssociationType; if (resourceAssociationType != null) { end1Name = resourceAssociationType.End1.Name; end1DeleteAction = resourceAssociationType.End1.DeleteBehavior; navigationProperty2Multiplicity = MetadataProviderUtils.ConvertMultiplicity(resourceAssociationType.End1.Multiplicity); end2Name = resourceAssociationType.End2.Name; end2DeleteAction = resourceAssociationType.End2.DeleteBehavior; navigationProperty1Multiplicity = MetadataProviderUtils.ConvertMultiplicity(resourceAssociationType.End2.Multiplicity); ResourceReferentialConstraint referentialConstraint = resourceAssociationType.ReferentialConstraint; if (referentialConstraint != null) { end1IsPrinciple = object.ReferenceEquals(resourceAssociationType.End1, referentialConstraint.PrincipalEnd); IEdmEntityType dependentEntityType = end1IsPrinciple ? (IEdmEntityType)this.EnsureSchemaType(resourceAssociationSet.End2.ResourceType) : (IEdmEntityType)this.EnsureSchemaType(resourceAssociationSet.End1.ResourceType); // now resolve all the dependent properties against the dependent entity type dependentProperties = new List<IEdmStructuralProperty>(); foreach (ResourceProperty dependentResourceProperty in referentialConstraint.DependentProperties) { IEdmProperty property = dependentEntityType.FindProperty(dependentResourceProperty.Name); Debug.Assert(property.PropertyKind == EdmPropertyKind.Structural, "Dependent properties must be structural."); dependentProperties.Add((IEdmStructuralProperty)property); } } } else { if (!isBiDirectional) { // If this association is not bi-directional, we use the type name as the from role name and the property name as the to role name // This is the behavior for V1. if (resourceAssociationSet.End1.ResourceProperty != null) { end1Name = resourceAssociationSet.End1.ResourceType.Name; end2Name = resourceAssociationSet.End1.ResourceProperty.Name; } else { end1Name = resourceAssociationSet.End2.ResourceProperty.Name; end2Name = resourceAssociationSet.End2.ResourceType.Name; } } else { // If the association is bi-directional, we use typeName_propertyName from each end as the name for that role end1Name = MetadataProviderUtils.GetAssociationEndName(resourceAssociationSet.End1.ResourceType, resourceAssociationSet.End1.ResourceProperty); end2Name = MetadataProviderUtils.GetAssociationEndName(resourceAssociationSet.End2.ResourceType, resourceAssociationSet.End2.ResourceProperty); Debug.Assert(end1Name != end2Name, "end1Name != end2Name"); } navigationProperty1Multiplicity = MetadataProviderUtils.GetMultiplicity(resourceAssociationSet.End1.ResourceProperty); end1DeleteAction = EdmOnDeleteAction.None; navigationProperty2Multiplicity = MetadataProviderUtils.GetMultiplicity(resourceAssociationSet.End2.ResourceProperty); end2DeleteAction = EdmOnDeleteAction.None; } string associationName = resourceAssociationType == null ? MetadataProviderUtils.GetAssociationName(resourceAssociationSet) : resourceAssociationType.Name; string associationNamespace; if (resourceAssociationType == null || resourceAssociationType.NamespaceName == null) { ResourceAssociationSetEnd end1 = resourceAssociationSet.End1.ResourceProperty != null ? resourceAssociationSet.End1 : resourceAssociationSet.End2; associationNamespace = this.GetTypeNamespace(end1.ResourceType); } else { associationNamespace = resourceAssociationType.NamespaceName; } ResourceProperty resourceProperty1 = resourceAssociationSet.End1.ResourceProperty; ResourceProperty resourceProperty2 = resourceAssociationSet.End2.ResourceProperty; MetadataProviderEdmNavigationProperty metadataNavigationProperty1 = null; MetadataProviderEdmNavigationProperty metadataNavigationProperty2 = null; if (resourceProperty1 != null) { IEdmEntityType entityType = (IEdmEntityType)this.EnsureSchemaType(resourceAssociationSet.End1.ResourceType); Debug.Assert(entityType != null, "entityType != null"); metadataNavigationProperty1 = (MetadataProviderEdmNavigationProperty)entityType.FindProperty(resourceProperty1.Name); Debug.Assert(metadataNavigationProperty1 != null, "metadataNavigationProperty1 != null"); } if (resourceProperty2 != null) { IEdmEntityType entityType = (IEdmEntityType)this.EnsureSchemaType(resourceAssociationSet.End2.ResourceType); Debug.Assert(entityType != null, "entityType != null"); metadataNavigationProperty2 = (MetadataProviderEdmNavigationProperty)entityType.FindProperty(resourceProperty2.Name); Debug.Assert(metadataNavigationProperty2 != null, "metadataNavigationProperty2 != null"); } IEdmNavigationProperty navigationProperty1 = (IEdmNavigationProperty)metadataNavigationProperty1; IEdmNavigationProperty navigationProperty2 = (IEdmNavigationProperty)metadataNavigationProperty2; MetadataProviderUtils.FixUpNavigationPropertyWithAssociationSetData(navigationProperty1, navigationProperty2, end1IsPrinciple, dependentProperties, end1DeleteAction, navigationProperty1Multiplicity); if (navigationProperty2 != null) { MetadataProviderUtils.FixUpNavigationPropertyWithAssociationSetData(navigationProperty2, navigationProperty1, !end1IsPrinciple, dependentProperties, end2DeleteAction, navigationProperty2Multiplicity); } MetadataProviderEdmEntitySet end1EntitySet = (MetadataProviderEdmEntitySet)this.EnsureEntitySet(this.metadataProvider.ValidateResourceSet(resourceAssociationSet.End1.ResourceSet)); MetadataProviderEdmEntitySet end2EntitySet = (MetadataProviderEdmEntitySet)this.EnsureEntitySet(this.metadataProvider.ValidateResourceSet(resourceAssociationSet.End2.ResourceSet)); if (metadataNavigationProperty1 != null) { end1EntitySet.EnsureNavigationTarget(metadataNavigationProperty1, end2EntitySet); } if (metadataNavigationProperty2 != null) { end2EntitySet.EnsureNavigationTarget(metadataNavigationProperty2, end1EntitySet); } }
/// <summary> /// Add the given association set. /// </summary> /// <param name="associationSet">association set to be added.</param> public void AddResourceAssociationSet(ResourceAssociationSet associationSet) { if (associationSet.End1.ResourceProperty != null) { this.associationSets.Add(GetAssociationKey(associationSet.End1), associationSet); } if (associationSet.End2.ResourceProperty != null) { this.associationSets.Add(GetAssociationKey(associationSet.End2), associationSet); } }
} // ServiceOperations public DSP.ResourceAssociationSet GetResourceAssociationSet(DSP.ResourceSet resourceSet, DSP.ResourceType resourceType, DSP.ResourceProperty resourceProperty) { if (associations == null) { associations = new Dictionary <string, DSP.ResourceAssociationSet>(); } DSP.ResourceType targetType = resourceProperty.ResourceType; DSP.ResourceSet targetSet = null; var targetContainers = this.containers.Where(c => IsAssignableFrom(c.ResourceType, targetType)); if (targetContainers.Count() == 1) { targetSet = targetContainers.First(); } else if (targetContainers.Count() > 1) { // MEST (uses naming convention) if (resourceSet.CustomState != null) { targetSet = targetContainers.Single(c => (string)c.CustomState == (string)resourceSet.CustomState); } else if (resourceProperty.CustomState != null) { targetSet = targetContainers.Single(c => (string)c.CustomState == (string)resourceProperty.CustomState); } else { throw new DataServiceException(500, "Cannot infer association set for MEST scenario"); } } string associationName = resourceSet.Name + "_" + resourceType.Name + '_' + resourceProperty.Name; if (associations.Keys.Contains(associationName)) { return(associations[associationName]); } else { DSP.ResourceProperty targetProperty = null; // Self links must be one-way if (resourceProperty.CustomState != null && (resourceSet != targetSet && resourceType != targetType)) { targetProperty = targetType.Properties.SingleOrDefault(p => p.CustomState != null && (string)p.CustomState == (string)resourceProperty.CustomState); } DSP.ResourceAssociationSetEnd sourceEnd = new DSP.ResourceAssociationSetEnd(resourceSet, resourceType, resourceProperty); DSP.ResourceAssociationSetEnd targetEnd = new DSP.ResourceAssociationSetEnd(targetSet, targetType, targetProperty); DSP.ResourceAssociationSet associationSet = new DSP.ResourceAssociationSet(associationName, sourceEnd, targetEnd); associations.Add(associationName, associationSet); // add to hash for target side if (targetProperty != null) { associationName = targetSet.Name + "_" + targetType.Name + '_' + targetProperty.Name; associations.Add(associationName, associationSet); } return(associationSet); } } // GetResourceAssociationSet
private static IDataServiceMetadataProvider PopulateMetadata(object dataSourceInstance) { List<ResourceType> types = new List<ResourceType>(4); ResourceType customer = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "Customer", false /*isAbstract*/); customer.CanReflectOnInstanceType = false; ResourceType order = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, "AstoriaUnitTests.Stubs", "Order", false); order.CanReflectOnInstanceType = false; ResourceType region = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "Region", false /*isAbstract*/); region.CanReflectOnInstanceType = false; ResourceType address = new ResourceType( typeof(RowComplexType), ResourceTypeKind.ComplexType, null, "AstoriaUnitTests.Stubs", "Address", false); address.CanReflectOnInstanceType = false; ResourceType product = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "Product", false /*isAbstract*/); product.CanReflectOnInstanceType = false; ResourceType orderDetail = new ResourceType( typeof(RowEntityType), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "OrderDetail", false /*isAbstract*/); orderDetail.CanReflectOnInstanceType = false; ResourceType currency = new ResourceType( typeof(RowComplexType), ResourceTypeKind.ComplexType, null, "AstoriaUnitTests.Stubs", "CurrencyAmount", false); ResourceType headquarter = new ResourceType( typeof(RowComplexType), ResourceTypeKind.ComplexType, null, "AstoriaUnitTests.Stubs", "Headquarter", false); headquarter.CanReflectOnInstanceType = false; ResourceSet customerEntitySet = new ResourceSet("Customers", customer); ResourceSet orderEntitySet = new ResourceSet("Orders", order); ResourceSet regionEntitySet = new ResourceSet("Regions", region); ResourceSet productEntitySet = new ResourceSet("Products", product); ResourceSet orderDetailEntitySet = new ResourceSet("OrderDetails", orderDetail); ResourceSet memberCustomerEntitySet = new ResourceSet("MemberCustomers", customer); ResourceSet memberOrderEntitySet = new ResourceSet("MemberOrders", order); ResourceSet memberRegionEntitySet = new ResourceSet("MemberRegions", region); ResourceSet memberProductEntitySet = new ResourceSet("MemberProducts", product); ResourceSet memberOrderDetailEntitySet = new ResourceSet("MemberOrderDetails", orderDetail); ResourceProperty keyProperty = new ResourceProperty( "ID", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int))); // populate customer properties customer.AddProperty(keyProperty); customer.AddProperty(CreateNonClrProperty("Name", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(String)))); customer.AddProperty(CreateNonClrProperty("BestFriend", ResourcePropertyKind.ResourceReference, customer)); customer.AddProperty(CreateNonClrProperty("Orders", ResourcePropertyKind.ResourceSetReference, order)); customer.AddProperty(CreateNonClrProperty("Region", ResourcePropertyKind.ResourceReference, region)); customer.AddProperty(CreateNonClrProperty("Address", ResourcePropertyKind.ComplexType, address)); customer.AddProperty(CreateNonClrProperty("GuidValue", ResourcePropertyKind.Primitive | ResourcePropertyKind.ETag, ResourceType.GetPrimitiveResourceType(typeof(Guid)))); ResourceProperty property = CreateNonClrProperty("NameAsHtml", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string))); property.MimeType = "text/html"; customer.AddProperty(property); if (OpenWebDataServiceHelper.EnableBlobServer) { customer.IsMediaLinkEntry = true; } // create Customer With Birthday and populate its properties ResourceType customerWithBirthday = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, customer, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "CustomerWithBirthday", false /*isAbstract*/); customerWithBirthday.AddProperty(CreateNonClrProperty("Birthday", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(DateTime)))); customerWithBirthday.CanReflectOnInstanceType = false; // populate order properties order.AddProperty(keyProperty); order.AddProperty(CreateNonClrProperty("DollarAmount", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(double)))); order.AddProperty(CreateNonClrProperty("OrderDetails", ResourcePropertyKind.ResourceSetReference, orderDetail)); order.AddProperty(CreateNonClrProperty("CurrencyAmount", ResourcePropertyKind.ComplexType, currency)); order.AddProperty(CreateNonClrProperty("Customer", ResourcePropertyKind.ResourceReference, customer)); // populate region properties region.AddProperty(keyProperty); region.AddProperty(CreateNonClrProperty("Name", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); region.AddProperty(CreateNonClrProperty("Headquarter", ResourcePropertyKind.ComplexType, headquarter)); //populate headquarter properties headquarter.AddProperty(CreateNonClrProperty("DrivingDirections", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); headquarter.AddProperty(CreateNonClrProperty("Address", ResourcePropertyKind.ComplexType, address)); //populate address properties address.AddProperty(CreateNonClrProperty("StreetAddress", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); address.AddProperty(CreateNonClrProperty("City", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); address.AddProperty(CreateNonClrProperty("State", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); address.AddProperty(CreateNonClrProperty("PostalCode", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); // create product type and its properties product.AddProperty(keyProperty); product.AddProperty(CreateNonClrProperty("ProductName", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(String)))); product.AddProperty(CreateNonClrProperty("Discontinued", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(bool)))); product.AddProperty(CreateNonClrProperty("OrderDetails", ResourcePropertyKind.ResourceSetReference, orderDetail)); // create order detail and its properties // DEVNOTE: it's very important that ProductID and OrderID are not in alphabetical order. There are tests relying on this. orderDetail.AddProperty(CreateNonClrProperty("ProductID", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)))); orderDetail.AddProperty(CreateNonClrProperty("OrderID", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)))); orderDetail.AddProperty(CreateNonClrProperty("UnitPrice", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(double)))); orderDetail.AddProperty(CreateNonClrProperty("Quantity", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(short)))); //populate currency amount properties currency.AddProperty(CreateNonClrProperty("Amount", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(decimal)))); currency.AddProperty(CreateNonClrProperty("CurrencyName", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(String)))); types.Add(customer); types.Add(customerWithBirthday); types.Add(order); types.Add(region); types.Add(address); types.Add(product); types.Add(orderDetail); types.Add(currency); types.Add(headquarter); List<ResourceSet> containers = new List<ResourceSet>(7); containers.Add(customerEntitySet); containers.Add(orderEntitySet); containers.Add(regionEntitySet); containers.Add(productEntitySet); containers.Add(orderDetailEntitySet); containers.Add(memberCustomerEntitySet); containers.Add(memberOrderEntitySet); containers.Add(memberRegionEntitySet); containers.Add(memberProductEntitySet); containers.Add(memberOrderDetailEntitySet); List<ServiceOperation> operations = new List<ServiceOperation>(1); operations.Add(new ServiceOperation("IntServiceOperation", ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), null, "GET", null)); operations.Add(new ServiceOperation("InsertCustomer", ServiceOperationResultKind.DirectValue, customer, customerEntitySet, "POST", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))), new ServiceOperationParameter("name", ResourceType.GetPrimitiveResourceType(typeof(string))) } )); operations.Add(new ServiceOperation("GetCustomerByCity", ServiceOperationResultKind.QueryWithMultipleResults, customer, customerEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("city", ResourceType.GetPrimitiveResourceType(typeof(string))) })); operations.Add(new ServiceOperation("DoNothingOperation", ServiceOperationResultKind.Void, null, null, "POST", null)); operations.Add(new ServiceOperation("GetCustomerAddress", ServiceOperationResultKind.DirectValue, address, null, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetOrderById", ServiceOperationResultKind.DirectValue, order, orderEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetRegionByName", ServiceOperationResultKind.QueryWithMultipleResults, region, regionEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("name", ResourceType.GetPrimitiveResourceType(typeof(string))) })); operations.Add(new ServiceOperation("AddressServiceOperation", ServiceOperationResultKind.DirectValue, address, null, "GET", null)); operations.Add(new ServiceOperation("GetAllCustomersQueryable", ServiceOperationResultKind.QueryWithMultipleResults, customer, customerEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetCustomerByIdQueryable", ServiceOperationResultKind.QueryWithSingleResult, customer, customerEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetAllCustomersEnumerable", ServiceOperationResultKind.Enumeration, customer, customerEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetCustomerByIdDirectValue", ServiceOperationResultKind.DirectValue, customer, customerEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetAllOrdersQueryable", ServiceOperationResultKind.QueryWithMultipleResults, order, orderEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetOrderByIdQueryable", ServiceOperationResultKind.QueryWithSingleResult, order, orderEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetAllOrdersEnumerable", ServiceOperationResultKind.Enumeration, order, orderEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetOrderByIdDirectValue", ServiceOperationResultKind.DirectValue, order, orderEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); List<ResourceAssociationSet> associationSets = new List<ResourceAssociationSet>(); ResourceAssociationSet customer_BestFriend = new ResourceAssociationSet( "Customers_BestFriend", new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "BestFriend")), new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "BestFriend"))); associationSets.Add(customer_BestFriend); ResourceAssociationSet customer_Order = new ResourceAssociationSet( "Customers_Orders", new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Orders")), new ResourceAssociationSetEnd(orderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(customer_Order); ResourceAssociationSet customer_Region = new ResourceAssociationSet( "Customers_Regions", new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Region")), new ResourceAssociationSetEnd(regionEntitySet, region, region.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(customer_Region); ResourceAssociationSet order_OrderDetails = new ResourceAssociationSet( "Orders_OrderDetails", new ResourceAssociationSetEnd(orderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(orderDetailEntitySet, orderDetail, null)); associationSets.Add(order_OrderDetails); ResourceAssociationSet product_OrderDetails = new ResourceAssociationSet( "Products_OrderDetails", new ResourceAssociationSetEnd(productEntitySet, product, product.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(orderDetailEntitySet, orderDetail, null)); associationSets.Add(product_OrderDetails); ResourceAssociationSet memberCustomer_BestFriend = new ResourceAssociationSet( "MemberCustomers_BestFriend", new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "BestFriend")), new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, null)); associationSets.Add(memberCustomer_BestFriend); ResourceAssociationSet memberCustomer_MemberOrder = new ResourceAssociationSet( "MemberCustomers_MemberOrders", new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Orders")), new ResourceAssociationSetEnd(memberOrderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(memberCustomer_MemberOrder); ResourceAssociationSet memberCustomer_MemberRegion = new ResourceAssociationSet( "MemberCustomers_MemberRegions", new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Region")), new ResourceAssociationSetEnd(memberRegionEntitySet, region, region.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(memberCustomer_MemberRegion); ResourceAssociationSet memberOrder_MemberOrderDetails = new ResourceAssociationSet( "MemberOrder_MemberOrderDetails", new ResourceAssociationSetEnd(memberOrderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(memberOrderDetailEntitySet, orderDetail, null)); associationSets.Add(memberOrder_MemberOrderDetails); ResourceAssociationSet memberProduct_MemberOrderDetails = new ResourceAssociationSet( "MemberProduct_MemberOrderDetails", new ResourceAssociationSetEnd(memberProductEntitySet, product, product.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(memberOrderDetailEntitySet, orderDetail, null)); associationSets.Add(memberProduct_MemberOrderDetails); return new CustomDataServiceProvider(containers, types, operations, associationSets, dataSourceInstance); }
/// <summary> /// Ensures that the product caches association sets based on the set/type/property name. /// </summary> /// <param name="associationSet">The association set which may or may-not be cached.</param> /// <param name="resourceSet">The resource set used to find the association set.</param> /// <param name="resourceType">Type of the resource used to find the association set.</param> /// <param name="resourceProperty">The resource property used to find the association set.</param> /// <param name="throwIfAlreadyCached">Whether or not to throw if the association set is already cached.</param> /// <returns>The same association set if not cached, or a copy if it was.</returns> private ResourceAssociationSet EnforceMetadataCache(ResourceAssociationSet associationSet, ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty, bool throwIfAlreadyCached) { if (!ProviderImplementationSettings.Current.EnforceMetadataCaching) { return associationSet; } var cacheKey = resourceSet.Name + "_" + resourceType.Name + "_" + (resourceProperty == null ? null : resourceProperty.Name); var end1 = associationSet.End1; var resourceSet1 = this.EnforceMetadataCache(end1.ResourceSet, false, true, true); var resourceType1 = this.EnforceMetadataCache(end1.ResourceType, false, true); var end2 = associationSet.End2; var resourceSet2 = this.EnforceMetadataCache(end2.ResourceSet, false, true, true); var resourceType2 = this.EnforceMetadataCache(end2.ResourceType, false, true); if (this.resourceAssociationSetCache.Add(cacheKey)) { return associationSet; } ExceptionUtilities.Assert(!throwIfAlreadyCached, "Association set with cache key '{0}' was resolved more than once", cacheKey); return new ResourceAssociationSet( associationSet.Name, new ResourceAssociationSetEnd(resourceSet1, resourceType1, null), new ResourceAssociationSetEnd(resourceSet2, resourceType2, null)); }
public override ResourceAssociationSet GetResourceAssociationSet(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty) { WebUtil.CheckArgumentNull(resourceSet, "resourceSet"); WebUtil.CheckArgumentNull(resourceType, "resourceType"); WebUtil.CheckArgumentNull(resourceProperty, "resourceProperty"); // Get source set EntitySet sourceEntitySet = this.GetEntitySet(resourceSet.Name); Debug.Assert(sourceEntitySet != null, "entitySet != null -- GetEntitySet should never return null"); // Get the source type EntityType sourceEntityType = this.ObjectContext.MetadataWorkspace.GetItem<EntityType>(resourceType.FullName, DataSpace.CSpace); Debug.Assert(sourceEntityType != null, "entityType != null"); // Get source navigation property NavigationProperty sourceNavigationProperty; sourceEntityType.NavigationProperties.TryGetValue(resourceProperty.Name, false /*ignoreCase*/, out sourceNavigationProperty); if (sourceNavigationProperty == null) { throw new InvalidOperationException(Strings.BadProvider_PropertyMustBeNavigationPropertyOnType(resourceProperty.Name, resourceType.FullName)); } if (sourceEntityType != (EntityType)sourceNavigationProperty.DeclaringType || resourceType != resourceType.GetDeclaringTypeForProperty(resourceProperty)) { throw new InvalidOperationException(Strings.BadProvider_ResourceTypeMustBeDeclaringTypeForProperty(resourceType.FullName, resourceProperty.Name)); } ResourceAssociationSet result = null; foreach (AssociationSet associationSet in sourceEntitySet.EntityContainer.BaseEntitySets.OfType<AssociationSet>()) { if (associationSet.ElementType == sourceNavigationProperty.RelationshipType) { // from AssociationSetEnd AssociationSetEnd setEnd = associationSet.AssociationSetEnds[sourceNavigationProperty.FromEndMember.Name]; if (setEnd.EntitySet == sourceEntitySet) { // from ResourceAssociationSetEnd ResourceAssociationSetEnd thisAssociationSetEnd = ObjectContextServiceProvider.PopulateResourceAssociationSetEnd(setEnd, resourceSet, resourceType, resourceProperty); #if !EF6Provider // from ResourceAssociationTypeEnd ResourceAssociationTypeEnd thisAssociationTypeEnd = ObjectContextServiceProvider.PopulateResourceAssociationTypeEnd( setEnd.CorrespondingAssociationEndMember, resourceType, resourceProperty); #endif // to AssociationSetEnd setEnd = associationSet.AssociationSetEnds[sourceNavigationProperty.ToEndMember.Name]; // Get the target resource set EntitySet targetEntitySet = setEnd.EntitySet; string targetEntitySetName = GetEntitySetName(targetEntitySet.Name, targetEntitySet.EntityContainer.Name, this.ObjectContext.DefaultContainerName == targetEntitySet.EntityContainer.Name); ResourceSet targetResourceSet; ((IDataServiceMetadataProvider)this).TryResolveResourceSet(targetEntitySetName, out targetResourceSet); Debug.Assert(targetResourceSet != null, "targetResourceSet != null"); // Get the target resource type EntityType targetEntityType = (EntityType)((RefType)sourceNavigationProperty.ToEndMember.TypeUsage.EdmType).ElementType; ResourceType targetResourceType; ((IDataServiceMetadataProvider)this).TryResolveResourceType(targetEntityType.FullName, out targetResourceType); Debug.Assert(targetResourceType != null, "targetResourceType != null"); // Get the target resource property ResourceProperty targetResourceProperty = null; foreach (NavigationProperty navProperty in targetEntityType.NavigationProperties) { if (navProperty.ToEndMember == sourceNavigationProperty.FromEndMember) { targetResourceProperty = targetResourceType.TryResolvePropertyName(navProperty.Name, exceptKind: ResourcePropertyKind.Stream); break; } } // to ResourceAssociationSetEnd ResourceAssociationSetEnd relatedAssociationSetEnd = ObjectContextServiceProvider.PopulateResourceAssociationSetEnd( setEnd, targetResourceSet, targetResourceType, (resourceType == targetResourceType && resourceProperty == targetResourceProperty) ? null : targetResourceProperty); #if !EF6Provider // to ResourceAssociationTypeEnd ResourceAssociationTypeEnd relatedAssociationTypeEnd = ObjectContextServiceProvider.PopulateResourceAssociationTypeEnd( setEnd.CorrespondingAssociationEndMember, targetResourceType, relatedAssociationSetEnd.ResourceProperty); #endif result = new ResourceAssociationSet(associationSet.Name, thisAssociationSetEnd, relatedAssociationSetEnd); #if !EF6Provider ObjectContextServiceProvider.PopulateAnnotations(associationSet.MetadataProperties, result.AddCustomAnnotation); result.ResourceAssociationType = ObjectContextServiceProvider.PopulateResourceAssociationType( associationSet.ElementType, thisAssociationTypeEnd, relatedAssociationTypeEnd); #endif break; } } } return result; }
public void AddResourceAssociationSet(ResourceAssociationSet associationSet) { this.resourceAssociationSets.Add(associationSet); }
public DefaultContainer_Metadata() { // ComplexTypes declared here Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType contactdetails_ComplexType = new Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType(typeof(Microsoft.Test.OData.Framework.TestProviders.Dictionary.ResourceInstance), ResourceTypeKind.ComplexType, null, "Microsoft.Test.OData.Services.OpenTypesService", "ContactDetails", false); contactdetails_ComplexType.IsOpenType = false; contactdetails_ComplexType.CanReflectOnInstanceType = false; this.ResourceTypes.Add(contactdetails_ComplexType); // ComplexTypes properties declared ResourceProperty contactdetails_FirstContacted = new ResourceProperty("FirstContacted", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(byte[]))); contactdetails_FirstContacted.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_FirstContacted); ResourceProperty contactdetails_LastContacted = new ResourceProperty("LastContacted", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(System.DateTimeOffset))); contactdetails_LastContacted.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_LastContacted); ResourceProperty contactdetails_Contacted = new ResourceProperty("Contacted", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(System.DateTimeOffset))); contactdetails_Contacted.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_Contacted); ResourceProperty contactdetails_GUID = new ResourceProperty("GUID", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(System.Guid))); contactdetails_GUID.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_GUID); ResourceProperty contactdetails_PreferedContactTime = new ResourceProperty("PreferedContactTime", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(System.TimeSpan))); contactdetails_PreferedContactTime.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_PreferedContactTime); ResourceProperty contactdetails_Byte = new ResourceProperty("Byte", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(byte))); contactdetails_Byte.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_Byte); ResourceProperty contactdetails_SignedByte = new ResourceProperty("SignedByte", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(sbyte))); contactdetails_SignedByte.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_SignedByte); ResourceProperty contactdetails_Double = new ResourceProperty("Double", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(double))); contactdetails_Double.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_Double); ResourceProperty contactdetails_Single = new ResourceProperty("Single", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(float))); contactdetails_Single.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_Single); ResourceProperty contactdetails_Short = new ResourceProperty("Short", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(short))); contactdetails_Short.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_Short); ResourceProperty contactdetails_Int = new ResourceProperty("Int", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int))); contactdetails_Int.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_Int); ResourceProperty contactdetails_Long = new ResourceProperty("Long", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(long))); contactdetails_Long.CanReflectOnInstanceTypeProperty = false; contactdetails_ComplexType.AddLazyProperty(contactdetails_Long); // EntityTypes declared here Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType row_EntityType = new Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType(typeof(Microsoft.Test.OData.Framework.TestProviders.Dictionary.ResourceInstance), ResourceTypeKind.EntityType, null, "Microsoft.Test.OData.Services.OpenTypesService", "Row", false); row_EntityType.IsOpenType = true; row_EntityType.CanReflectOnInstanceType = false; this.ResourceTypes.Add(row_EntityType); Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType indexedrow_EntityType = new Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType(typeof(Microsoft.Test.OData.Framework.TestProviders.Dictionary.ResourceInstance), ResourceTypeKind.EntityType, row_EntityType, "Microsoft.Test.OData.Services.OpenTypesService", "IndexedRow", false); indexedrow_EntityType.IsOpenType = true; indexedrow_EntityType.CanReflectOnInstanceType = false; this.ResourceTypes.Add(indexedrow_EntityType); Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType rowindex_EntityType = new Microsoft.Test.OData.Framework.TestProviders.Common.LazyResourceType(typeof(Microsoft.Test.OData.Framework.TestProviders.Dictionary.ResourceInstance), ResourceTypeKind.EntityType, null, "Microsoft.Test.OData.Services.OpenTypesService", "RowIndex", false); rowindex_EntityType.IsOpenType = true; rowindex_EntityType.CanReflectOnInstanceType = false; this.ResourceTypes.Add(rowindex_EntityType); // EntityType primitive and complexType properties declared here ResourceProperty row_Id = new ResourceProperty("Id", (ResourcePropertyKind.Primitive | ResourcePropertyKind.Key), ResourceType.GetPrimitiveResourceType(typeof(System.Guid))); row_Id.CanReflectOnInstanceTypeProperty = false; row_EntityType.AddLazyProperty(row_Id); ResourceProperty rowindex_Id = new ResourceProperty("Id", (ResourcePropertyKind.Primitive | ResourcePropertyKind.Key), ResourceType.GetPrimitiveResourceType(typeof(int))); rowindex_Id.CanReflectOnInstanceTypeProperty = false; rowindex_EntityType.AddLazyProperty(rowindex_Id); // EntityTypes navigation properties declared here ResourceProperty rowindex_Rows = new ResourceProperty("Rows", ResourcePropertyKind.ResourceSetReference, indexedrow_EntityType); rowindex_Rows.CanReflectOnInstanceTypeProperty = false; rowindex_EntityType.AddLazyProperty(rowindex_Rows); // Add EntitySet Declarations var row_EntitySet = new ResourceSet("Row", row_EntityType); this.ResourceSets.Add(row_EntitySet); var rowindex_EntitySet = new ResourceSet("RowIndex", rowindex_EntityType); this.ResourceSets.Add(rowindex_EntitySet); // Add AssociationSet Declarations Microsoft.OData.Service.Providers.ResourceAssociationSet index_rows_AssociationSet = new ResourceAssociationSet("Index_Rows", new ResourceAssociationSetEnd(rowindex_EntitySet, rowindex_EntityType, rowindex_Rows), new ResourceAssociationSetEnd(row_EntitySet, indexedrow_EntityType, null)); this.ResourceAssociationSets.Add(index_rows_AssociationSet); // ServiceOperations declared here row_EntitySet.SetReadOnly(); rowindex_EntitySet.SetReadOnly(); row_EntityType.SetReadOnly(); indexedrow_EntityType.SetReadOnly(); rowindex_EntityType.SetReadOnly(); contactdetails_ComplexType.SetReadOnly(); }