/// <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);
            }
        }
Esempio n. 2
0
        /// <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);
            }
        }
Esempio n. 3
0
        } // 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();

        }