private ProductSearchResultContainer AssembleProducts(
                GetProductPartsDataResponse productPartsResponse,
                ReadOnlyCollection <UnitOfMeasureConversion> unitOfMeasureOptionsDataSet,
                ReadOnlyCollection <KitDefinition> kitDefinitions,
                ReadOnlyCollection <KitComponent> kitComponentAndSubstituteList,
                ReadOnlyCollection <KitConfigToComponentAssociation> kitConfigToComponentAssociations,
                ReadOnlyCollection <KitComponent> parentKitsComponentInfo)
            {
                var productSearchResult = new ProductSearchResultContainer();

                var productParts = new Tuple <ReadOnlyCollection <ProductIdentity>, ReadOnlyCollection <ProductVariant>, ReadOnlyCollection <ProductRules>, ReadOnlyCollection <ProductAttributeSchemaEntry>, ReadOnlyCollection <ProductProperty>, ReadOnlyCollection <ProductCatalog>, ReadOnlyCollection <ProductCategoryAssociation>, Tuple <ReadOnlyCollection <RelatedProduct> > >(
                    productPartsResponse.ProductIdentities,
                    productPartsResponse.ProductVariants,
                    productPartsResponse.ProductRules,
                    productPartsResponse.ProductAttributeSchemaEntries,
                    productPartsResponse.ProductProperties,
                    productPartsResponse.ProductCatalogs,
                    productPartsResponse.CategoryAssociations,
                    new Tuple <ReadOnlyCollection <RelatedProduct> >(productPartsResponse.RelatedProducts));

                ProductBuilder.AssembleProductsFromDataSets(
                    this.request.Criteria.Context,
                    this.request.Criteria.DataLevel,
                    productParts,
                    productPartsResponse.LinkedProducts,
                    kitDefinitions,
                    kitComponentAndSubstituteList,
                    kitConfigToComponentAssociations,
                    parentKitsComponentInfo,
                    unitOfMeasureOptionsDataSet,
                    productSearchResult,
                    this.request.RequestContext.GetChannelConfiguration().ProductDefaultImageTemplate);

                return(productSearchResult);
            }
            /// <summary>
            /// Get products based on the <see cref="request" />.
            /// </summary>
            /// <param name="criteria">The criteria.</param>
            /// <returns>
            /// The <see cref="ProductSearchResultContainer" /> containing the requested products.
            /// </returns>
            private ProductSearchResultContainer GetProductsFromDbStorage(ProductSearchCriteria criteria)
            {
                GetProductPartsDataResponse   productPartsResponse = this.GetProductParts(criteria);
                IEnumerable <ProductIdentity> productIdentities    = productPartsResponse.ProductIdentities;

                ReadOnlyCollection <UnitOfMeasureConversion>         unitOfMeasureOptionsDataSet;
                ReadOnlyCollection <KitDefinition>                   kitDefinitions;
                ReadOnlyCollection <KitComponent>                    kitComponentAndSubstituteList;
                ReadOnlyCollection <KitConfigToComponentAssociation> kitConfigToComponentAssociations;
                ReadOnlyCollection <KitComponent>                    parentKitsComponentInfo;

                if (criteria.DataLevel >= CommerceEntityDataLevel.Extended)
                {
                    IList <long> masterIds    = productIdentities.Where(i => i.IsMasterProduct).Select(t => t.LookupId).ToList();
                    IList <long> kitMasterIds = productIdentities.Where(i => i.IsKitProduct).Select(t => t.LookupId).ToList();
                    IList <long> allIds       = productIdentities.Select(i => i.RecordId).ToList();

                    // unit of measure
                    unitOfMeasureOptionsDataSet = this.GetUnitOfMeasureOptions(allIds);

                    // kits
                    this.GetKits(
                        masterIds,
                        kitMasterIds,
                        allIds,
                        out kitDefinitions,
                        out kitComponentAndSubstituteList,
                        out kitConfigToComponentAssociations,
                        out parentKitsComponentInfo);
                }
                else
                {
                    // lower data levels don't contain this information
                    unitOfMeasureOptionsDataSet = new ReadOnlyCollection <UnitOfMeasureConversion>(new List <UnitOfMeasureConversion>());
                    kitDefinitions = new ReadOnlyCollection <KitDefinition>(new List <KitDefinition>());
                    kitComponentAndSubstituteList    = new ReadOnlyCollection <KitComponent>(new List <KitComponent>());
                    kitConfigToComponentAssociations = new ReadOnlyCollection <KitConfigToComponentAssociation>(new List <KitConfigToComponentAssociation>());
                    parentKitsComponentInfo          = new ReadOnlyCollection <KitComponent>(new List <KitComponent>());
                }

                return(this.AssembleProducts(
                           productPartsResponse,
                           unitOfMeasureOptionsDataSet,
                           kitDefinitions,
                           kitComponentAndSubstituteList,
                           kitConfigToComponentAssociations,
                           parentKitsComponentInfo));
            }