private static GetLinkedProductsDataResponse GetLinkedProducts(GetLinkedProductsDataRequest request)
            {
                ReadOnlyCollection <LinkedProduct> linkedProducts;

                using (SqliteDatabaseContext context = new SqliteDatabaseContext(request.RequestContext))
                {
                    GetLinkedProductsProcedure getLinkedProductsProcedure = new GetLinkedProductsProcedure(context, context.ChannelId, request.ProductIds);
                    linkedProducts = getLinkedProductsProcedure.Execute();
                }

                return(new GetLinkedProductsDataResponse(linkedProducts));
            }
            public GetProductPartsDataResponse Execute()
            {
                ReadOnlyCollection <ProductIdentity>             productIdentities;
                ReadOnlyCollection <ProductVariant>              productVariants;
                ReadOnlyCollection <ProductProperty>             productProperties;
                ReadOnlyCollection <ProductAttributeSchemaEntry> productAttributeSchemaEntries;
                ReadOnlyCollection <ProductRules>               productRules;
                ReadOnlyCollection <ProductCatalog>             productCatalogs;
                ReadOnlyCollection <ProductCategoryAssociation> categoryAssociations;
                ReadOnlyCollection <RelatedProduct>             relatedProducts;
                ReadOnlyCollection <LinkedProduct>              linkedProducts;

                using (SqliteDatabaseContext context = new SqliteDatabaseContext(this.request.RequestContext))
                {
                    // use the channel id on the request, or context.ChannelId if none was provided in the request
                    long channelId = this.request.Criteria.Context.ChannelId.GetValueOrDefault(context.ChannelId);

                    using (TempTable assortedProducts = this.GetAssortedProductsTable(context, channelId, this.request.Criteria.SkipVariantExpansion))
                    {
                        // get product identities (product id, master id, variant id, item id...)
                        productIdentities = this.GetProductIdentities(context, assortedProducts);

                        // get variant details (dimensions, variant item id...)
                        productVariants = this.GetProductVariants(context, assortedProducts);

                        // get product attributes (name, variant localized names...)
                        var productAttributeProcedure = new GetProductAttributesProcedure(
                            context,
                            assortedProducts,
                            channelId,
                            this.request.LanguageId);

                        productAttributeProcedure.GetAttributes(out productAttributeSchemaEntries, out productProperties);

                        // get product rules (is serializable, should be weighted, etc...)
                        productRules = this.GetProductRules(context, assortedProducts);

                        productCatalogs      = new ReadOnlyCollection <ProductCatalog>(new ProductCatalog[0]);
                        categoryAssociations = new ReadOnlyCollection <ProductCategoryAssociation>(new ProductCategoryAssociation[0]);

                        if (this.request.Criteria.DataLevel >= CommerceEntityDataLevel.Extended)
                        {
                            GetLinkedProductsProcedure getLinkedProductsProcedure = new GetLinkedProductsProcedure(context, channelId, assortedProducts);
                            linkedProducts = getLinkedProductsProcedure.Execute();

                            // Related products
                            relatedProducts = this.GetProductRelations(context, assortedProducts);
                        }
                        else
                        {
                            linkedProducts  = new ReadOnlyCollection <LinkedProduct>(new LinkedProduct[0]);
                            relatedProducts = new ReadOnlyCollection <RelatedProduct>(new RelatedProduct[0]);
                        }
                    }
                }

                return(new GetProductPartsDataResponse(
                           productIdentities,
                           productVariants,
                           productProperties,
                           productAttributeSchemaEntries,
                           productRules,
                           productCatalogs,
                           categoryAssociations,
                           relatedProducts,
                           linkedProducts));
            }