protected virtual async Task <IDictionary <string, Category> > PreloadCategoriesAsync(string catalogId) { var cacheKey = CacheKey.With(GetType(), "PreloadCategories", catalogId); return(await _platformMemoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); CategoryEntity[] entities; using (var repository = _repositoryFactory()) { repository.DisableChangesTracking(); entities = await repository.GetCategoriesByIdsAsync(repository.Categories.Select(x => x.Id).ToArray(), CategoryResponseGroup.Full); } var result = entities.Select(x => x.ToModel(AbstractTypeFactory <Category> .TryCreateInstance())) .ToDictionary(x => x.Id, StringComparer.OrdinalIgnoreCase) .WithDefaultValue(null); await LoadDependenciesAsync(result.Values, result); ApplyInheritanceRules(result.Values); // Fill outlines for categories _outlineService.FillOutlinesForObjects(result.Values, catalogId); return result; })); }
protected virtual Task <IDictionary <string, Catalog> > PreloadCatalogs() { var cacheKey = CacheKey.With(GetType(), "AllCatalogs"); return(_platformMemoryCache.GetOrCreateExclusive(cacheKey, async(cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); CatalogEntity[] entities; using (var repository = _repositoryFactory()) { //Optimize performance and CPU usage repository.DisableChangesTracking(); var ids = await repository.Catalogs.Select(x => x.Id).ToArrayAsync(); entities = await repository.GetCatalogsByIdsAsync(ids); } var result = entities.Select(x => x.ToModel(AbstractTypeFactory <Catalog> .TryCreateInstance())) .ToDictionary(x => x.Id, StringComparer.OrdinalIgnoreCase) .WithDefaultValue(null); LoadDependencies(result.Values, result); return result; })); }
public async Task DeleteAsync(IEnumerable <string> ids, bool doDeleteValues = false) { using (var repository = _repositoryFactory()) { var entities = await repository.GetPropertiesByIdsAsync(ids.ToArray()); //Raise domain events before deletion var changedEntries = entities.Select(x => new GenericChangedEntry <Property>(x.ToModel(AbstractTypeFactory <Property> .TryCreateInstance()), EntryState.Deleted)); await _eventPublisher.Publish(new PropertyChangingEvent(changedEntries)); foreach (var entity in entities) { repository.Remove(entity); if (doDeleteValues) { await repository.RemoveAllPropertyValuesAsync(entity.Id); } } await repository.UnitOfWork.CommitAsync(); await _eventPublisher.Publish(new PropertyChangedEvent(changedEntries)); //Reset catalog cache CatalogCacheRegion.ExpireRegion(); } }
protected virtual Dictionary <string, Category> PreloadCategories(string catalogId) { var cacheKey = CacheKey.With(GetType(), "PreloadCategories", catalogId); return(_memoryCache.GetOrCreateExclusive(cacheKey, (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); CategoryEntity[] entities; using (var repository = _repositoryFactory()) { repository.DisableChangesTracking(); entities = repository.GetCategoriesByIds(repository.Categories.Select(x => x.Id).ToArray()); } var result = entities.Select(x => x.ToModel(AbstractTypeFactory <Category> .TryCreateInstance())).ToDictionary(x => x.Id, StringComparer.OrdinalIgnoreCase); LoadDependencies(result.Values, result); ApplyInheritanceRules(result.Values.OrderBy(x => x.Level)); // Fill outlines for categories _outlineService.FillOutlinesForObjects(result.Values, catalogId); var objectsWithSeo = new List <ISeoSupport>(result.Values); var outlineItems = result.Values.Where(c => c.Outlines != null).SelectMany(c => c.Outlines.SelectMany(o => o.Items)); objectsWithSeo.AddRange(outlineItems); //TODO: convert to async _seoService.LoadSeoForObjectsAsync(objectsWithSeo.ToArray()); return result; })); }
public virtual async Task <CatalogProduct[]> GetByIdsAsync(string[] itemIds, string respGroup, string catalogId = null) { var itemResponseGroup = EnumUtility.SafeParseFlags(respGroup, ItemResponseGroup.ItemLarge); var cacheKey = CacheKey.With(GetType(), nameof(GetByIdsAsync), string.Join("-", itemIds), itemResponseGroup.ToString(), catalogId); var result = await _platformMemoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { var products = Array.Empty <CatalogProduct>(); if (!itemIds.IsNullOrEmpty()) { using (var repository = _repositoryFactory()) { //Optimize performance and CPU usage repository.DisableChangesTracking(); //It is so important to generate change tokens for all ids even for not existing objects to prevent an issue //with caching of empty results for non - existing objects that have the infinitive lifetime in the cache //and future unavailability to create objects with these ids. cacheEntry.AddExpirationToken(ItemCacheRegion.CreateChangeToken(itemIds)); cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); products = (await repository.GetItemByIdsAsync(itemIds, respGroup)) .Select(x => x.ToModel(AbstractTypeFactory <CatalogProduct> .TryCreateInstance())) .ToArray(); } if (products.Any()) { products = products.OrderBy(x => Array.IndexOf(itemIds, x.Id)).ToArray(); await LoadDependenciesAsync(products); ApplyInheritanceRules(products); var productsWithVariationsList = products.Concat(products.Where(p => p.Variations != null) .SelectMany(p => p.Variations)).ToArray(); // Fill outlines for products and variations if (itemResponseGroup.HasFlag(ItemResponseGroup.Outlines)) { _outlineService.FillOutlinesForObjects(productsWithVariationsList, catalogId); } //Add change tokens for products with variations cacheEntry.AddExpirationToken(ItemCacheRegion.CreateChangeToken(productsWithVariationsList)); //Reduce details according to response group foreach (var product in productsWithVariationsList) { product.ReduceDetails(itemResponseGroup.ToString()); } } } return(products); }); return(result.Select(x => x.Clone() as CatalogProduct).ToArray()); }
/// <summary> /// Async search products by given criteria /// </summary> /// <param name="criteria"></param> /// <returns></returns> public virtual async Task <CatalogSearchResult> SearchProductsAsync(ProductSearchCriteria criteria) { var workContext = _workContextAccessor.WorkContext; var cacheKey = CacheKey.With(GetType(), "SearchProductsAsync", criteria.GetCacheKey(), workContext.CurrentStore.Id, workContext.CurrentLanguage.CultureName, workContext.CurrentCurrency.Code); return(await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(_apiChangesWatcher.CreateChangeToken()); criteria = criteria.Clone(); var searchCriteria = criteria.ToProductSearchCriteriaDto(workContext); var result = await _searchApi.SearchProductsAsync(searchCriteria); var products = result.Items?.Select(x => x.ToProduct(workContext.CurrentLanguage, workContext.CurrentCurrency, workContext.CurrentStore)).ToList() ?? new List <Product>(); if (products.Any()) { var productsWithVariations = products.Concat(products.SelectMany(x => x.Variations)).ToList(); var taskList = new List <Task>(); if (criteria.ResponseGroup.HasFlag(ItemResponseGroup.Inventory)) { taskList.Add(LoadProductInventoriesAsync(productsWithVariations, workContext)); } if (criteria.ResponseGroup.HasFlag(ItemResponseGroup.ItemAssociations)) { taskList.Add(LoadProductsAssociationsAsync(productsWithVariations, workContext)); } if (criteria.ResponseGroup.HasFlag(ItemResponseGroup.ItemWithVendor)) { taskList.Add(LoadProductVendorsAsync(productsWithVariations, workContext)); } if (criteria.ResponseGroup.HasFlag(ItemResponseGroup.ItemWithPrices)) { taskList.Add(_pricingService.EvaluateProductPricesAsync(productsWithVariations, workContext)); } await Task.WhenAll(taskList.ToArray()); foreach (var product in productsWithVariations) { product.IsBuyable = new ProductIsBuyableSpecification().IsSatisfiedBy(product); product.IsAvailable = new ProductIsAvailableSpecification(product).IsSatisfiedBy(1); product.IsInStock = new ProductIsInStockSpecification().IsSatisfiedBy(product); } } return new CatalogSearchResult { Products = new StaticPagedList <Product>(products, criteria.PageNumber, criteria.PageSize, (int?)result.TotalCount ?? 0), Aggregations = !result.Aggregations.IsNullOrEmpty() ? result.Aggregations.Select(x => x.ToAggregation(workContext.CurrentLanguage.CultureName)).ToArray() : new Aggregation[] { } }; })); }
protected virtual async Task <Product[]> GetProductsAsync(IList <string> ids, ItemResponseGroup responseGroup, WorkContext workContext) { var cacheKey = CacheKey.With(GetType(), "GetProductsAsync", string.Join("-", ids.OrderBy(x => x)), responseGroup.ToString()); var result = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(_apiChangesWatcher.CreateChangeToken()); return(await _productsApi.GetProductByPlentyIdsAsync(ids, ((int)responseGroup).ToString())); }); return(result.Select(x => x.ToProduct(workContext.CurrentLanguage, workContext.CurrentCurrency, workContext.CurrentStore)).ToArray()); }
private async Task <Category[]> InnerGetCategoriesAsync(string[] ids, WorkContext workContext, CategoryResponseGroup responseGroup = CategoryResponseGroup.Info) { var cacheKey = CacheKey.With(GetType(), "InnerGetCategoriesAsync", string.Join("-", ids.OrderBy(x => x)), responseGroup.ToString()); var categoriesDto = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); return(await _categoriesApi.GetCategoriesByPlentyIdsAsync(ids.ToList(), ((int)responseGroup).ToString())); }); var result = categoriesDto.Select(x => x.ToCategory(workContext.CurrentLanguage, workContext.CurrentStore)).ToArray(); //Set lazy loading for child categories SetChildCategoriesLazyLoading(result); return(result); }
protected virtual async Task <catalogDto.ProductSearchResult> SearchProductsAsync(ProductSearchCriteria criteria, WorkContext workContext) { var cacheKey = CacheKey.With(GetType(), "SearchProductsAsync", criteria.GetCacheKey(), workContext.CurrentStore.Id, workContext.CurrentLanguage.CultureName, workContext.CurrentCurrency.Code); return(await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(_apiChangesWatcher.CreateChangeToken()); criteria = criteria.Clone() as ProductSearchCriteria; var searchCriteria = criteria.ToProductSearchCriteriaDto(workContext); return await _searchApi.SearchProductsAsync(searchCriteria); })); }
protected virtual Task LoadProductsAssociationsAsync(IEnumerable <Product> products, WorkContext workContext) { if (products == null) { throw new ArgumentNullException(nameof(products)); } foreach (var product in products) { //Associations product.Associations = new MutablePagedList <ProductAssociation>((pageNumber, pageSize, sortInfos, @params) => { var criteria = new ProductAssociationSearchCriteria { PageNumber = pageNumber, PageSize = pageSize, ProductId = product.Id, ResponseGroup = ItemResponseGroup.ItemInfo | ItemResponseGroup.ItemWithPrices | ItemResponseGroup.Inventory | ItemResponseGroup.ItemWithVendor }; if (!sortInfos.IsNullOrEmpty()) { criteria.Sort = SortInfo.ToString(sortInfos); } if (@params != null) { criteria.CopyFrom(@params); } var cacheKey = CacheKey.With(GetType(), "SearchProductAssociations", criteria.GetCacheKey()); var searchResult = _memoryCache.GetOrCreateExclusive(cacheKey, cacheEntry => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(_apiChangesWatcher.CreateChangeToken()); return(_productsApi.SearchProductAssociations(criteria.ToProductAssociationSearchCriteriaDto())); }); //Load products for resulting associations var associatedProducts = GetProductsAsync(searchResult.Results.Select(x => x.AssociatedObjectId).ToArray(), criteria.ResponseGroup).GetAwaiter().GetResult(); var result = new List <ProductAssociation>(); foreach (var associationDto in searchResult.Results) { var productAssociation = associationDto.ToProductAssociation(); productAssociation.Product = associatedProducts.FirstOrDefault(x => x.Id.EqualsInvariant(productAssociation.ProductId)); result.Add(productAssociation); } return(new StaticPagedList <ProductAssociation>(result, pageNumber, pageSize, searchResult.TotalCount ?? 0)); }, 1, ProductSearchCriteria.DefaultPageSize); } return(Task.CompletedTask); }
public virtual async Task <Category[]> GetCategoriesAsync(string[] ids, CategoryResponseGroup responseGroup = CategoryResponseGroup.Info) { var workContext = _workContextAccessor.WorkContext; var cacheKey = CacheKey.With(GetType(), "GetCategoriesAsync", string.Join("-", ids.OrderBy(x => x)), responseGroup.ToString()); var categoriesDto = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); return(await _categoriesApi.GetCategoriesByPlentyIdsAsync(ids.ToList(), ((int)responseGroup).ToString())); }); var result = categoriesDto.Select(x => x.ToCategory(workContext.CurrentLanguage, workContext.CurrentStore)).ToArray(); //Set lazy loading for child categories EstablishLazyDependenciesForCategories(result); return(result); }
public async Task SaveChangesAsync(IEnumerable <Property> properties) { var pkMap = new PrimaryKeyResolvingMap(); var changedEntries = new List <GenericChangedEntry <Property> >(); ValidateProperties(properties); using (var repository = _repositoryFactory()) { TryAddPredefinedValidationRules(properties); var dbExistProperties = await repository.GetPropertiesByIdsAsync(properties.Where(x => !x.IsTransient()).Select(x => x.Id).ToArray()); foreach (var property in properties) { var modifiedEntity = AbstractTypeFactory <PropertyEntity> .TryCreateInstance().FromModel(property, pkMap); var originalEntity = dbExistProperties.FirstOrDefault(x => x.Id == property.Id); if (originalEntity != null) { changedEntries.Add(new GenericChangedEntry <Property>(property, originalEntity.ToModel(AbstractTypeFactory <Property> .TryCreateInstance()), EntryState.Modified)); modifiedEntity.Patch(originalEntity); //Force set ModifiedDate property to mark a product changed. Special for partial update cases when product table not have changes originalEntity.ModifiedDate = DateTime.UtcNow; } else { repository.Add(modifiedEntity); changedEntries.Add(new GenericChangedEntry <Property>(property, EntryState.Added)); } } //Raise domain events await _eventPublisher.Publish(new PropertyChangingEvent(changedEntries)); //Save changes in database await repository.UnitOfWork.CommitAsync(); pkMap.ResolvePrimaryKeys(); //Reset catalog cache CatalogCacheRegion.ExpireRegion(); await _eventPublisher.Publish(new PropertyChangedEvent(changedEntries)); } }
public void Delete(IEnumerable <string> catalogIds) { var catalogs = GetByIds(catalogIds); //Raise domain events before deletion var changedEntries = catalogs.Select(x => new GenericChangedEntry <Catalog>(x, EntryState.Deleted)); _eventPublisher.Publish(new CatalogChangingEvent(changedEntries)); using (var repository = _repositoryFactory()) { //TODO: raise events on catalog deletion repository.RemoveCatalogs(catalogIds.ToArray()); repository.UnitOfWork.Commit(); //Reset cached catalogs and catalogs CatalogCacheRegion.ExpireRegion(); } _eventPublisher.Publish(new CatalogChangedEvent(changedEntries)); }
public virtual async Task <CatalogProduct[]> GetByIdsAsync(string[] itemIds, string responseGroup, string catalogId = null) { var itemResponseGroup = EnumUtility.SafeParseFlags(responseGroup, ItemResponseGroup.ItemLarge); var cacheKey = CacheKey.With(GetType(), "GetByIdsAsync", string.Join("-", itemIds), itemResponseGroup.ToString(), catalogId); return(await _platformMemoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { CatalogProduct[] result; using (var repository = _repositoryFactory()) { //Optimize performance and CPU usage repository.DisableChangesTracking(); result = (await repository.GetItemByIdsAsync(itemIds, itemResponseGroup)) .Select(x => x.ToModel(AbstractTypeFactory <CatalogProduct> .TryCreateInstance())) .ToArray(); } await LoadDependenciesAsync(result); var productsWithVariationsList = result.Concat(result.Where(p => p.Variations != null) .SelectMany(p => p.Variations)).ToArray(); ApplyInheritanceRules(productsWithVariationsList); // Fill outlines for products and variations if (itemResponseGroup.HasFlag(ItemResponseGroup.Outlines)) { _outlineService.FillOutlinesForObjects(productsWithVariationsList, catalogId); } //Reduce details according to response group foreach (var product in productsWithVariationsList) { product.ReduceDetails(itemResponseGroup.ToString()); cacheEntry.AddExpirationToken(ItemCacheRegion.CreateChangeToken(product)); cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); } return result; })); }
public virtual async Task DeleteAsync(string[] catalogIds) { using (var repository = _repositoryFactory()) { var catalogs = await GetByIdsAsync(catalogIds); if (!catalogs.IsNullOrEmpty()) { var changedEntries = catalogs.Select(x => new GenericChangedEntry <Catalog>(x, EntryState.Deleted)); await _eventPublisher.Publish(new CatalogChangingEvent(changedEntries)); await repository.RemoveCatalogsAsync(catalogs.Select(m => m.Id).ToArray()); await repository.UnitOfWork.CommitAsync(); await _eventPublisher.Publish(new CatalogChangedEvent(changedEntries)); } } CatalogCacheRegion.ExpireRegion(); }
public ActionResult ResetCache() { //TODO: Replace to some other (maybe with using reflection) ThemeEngineCacheRegion.ExpireRegion(); CartCacheRegion.ExpireRegion(); CatalogCacheRegion.ExpireRegion(); ContentBlobCacheRegion.ExpireRegion(); CustomerCacheRegion.ExpireRegion(); MarketingCacheRegion.ExpireRegion(); PricingCacheRegion.ExpireRegion(); QuoteCacheRegion.ExpireRegion(); RecommendationsCacheRegion.ExpireRegion(); StaticContentCacheRegion.ExpireRegion(); StoreCacheRegion.ExpireRegion(); TaxCacheRegion.ExpireRegion(); SubscriptionCacheRegion.ExpireRegion(); SecurityCacheRegion.ExpireRegion(); return(StoreFrontRedirect("~/")); }
public virtual async Task DeleteAsync(string[] categoryIds) { var categories = await GetByIdsAsync(categoryIds, CategoryResponseGroup.Info.ToString()); var changedEntries = categories .Select(c => new GenericChangedEntry <Category>(c, EntryState.Deleted)) .ToList(); using (var repository = _repositoryFactory()) { await _eventPublisher.Publish(new CategoryChangingEvent(changedEntries)); await repository.RemoveCategoriesAsync(categoryIds); await repository.UnitOfWork.CommitAsync(); CatalogCacheRegion.ExpireRegion(); await _eventPublisher.Publish(new CategoryChangedEvent(changedEntries)); } }
public virtual void SaveChanges(IEnumerable <Category> categories) { var pkMap = new PrimaryKeyResolvingMap(); var changedEntries = new List <GenericChangedEntry <Category> >(); ValidateCategoryProperties(categories); using (var repository = _repositoryFactory()) { var dbExistCategories = repository.GetCategoriesByIds(categories.Where(x => !x.IsTransient()).Select(x => x.Id).ToArray()); foreach (var category in categories) { var originalEntity = dbExistCategories.FirstOrDefault(x => x.Id == category.Id); var modifiedEntity = AbstractTypeFactory <CategoryEntity> .TryCreateInstance().FromModel(category, pkMap); if (originalEntity != null) { changedEntries.Add(new GenericChangedEntry <Category>(category, originalEntity.ToModel(AbstractTypeFactory <Category> .TryCreateInstance()), EntryState.Modified)); modifiedEntity.Patch(originalEntity); //Force set ModifiedDate property to mark a product changed. Special for partial update cases when product table not have changes originalEntity.ModifiedDate = DateTime.UtcNow; } else { repository.Add(modifiedEntity); changedEntries.Add(new GenericChangedEntry <Category>(category, EntryState.Added)); } } //Raise domain events _eventPublisher.Publish(new CategoryChangingEvent(changedEntries)); //Save changes in database repository.UnitOfWork.Commit(); pkMap.ResolvePrimaryKeys(); _eventPublisher.Publish(new CategoryChangedEvent(changedEntries)); //Reset catalog cache CatalogCacheRegion.ExpireRegion(); } //Need add seo separately _seoService.SaveSeoForObjectsAsync(categories.OfType <ISeoSupport>().ToArray()); }
public virtual async Task SaveChangesAsync(Catalog[] catalogs) { var pkMap = new PrimaryKeyResolvingMap(); var changedEntries = new List <GenericChangedEntry <Catalog> >(); using (var repository = _repositoryFactory()) { await ValidateCatalogPropertiesAsync(catalogs); var dbExistEntities = await repository.GetCatalogsByIdsAsync(catalogs.Where(x => !x.IsTransient()).Select(x => x.Id).ToArray()); foreach (var catalog in catalogs) { var originalEntity = dbExistEntities.FirstOrDefault(x => x.Id == catalog.Id); var modifiedEntity = AbstractTypeFactory <CatalogEntity> .TryCreateInstance().FromModel(catalog, pkMap); if (originalEntity != null) { changedEntries.Add(new GenericChangedEntry <Catalog>(catalog, originalEntity.ToModel(AbstractTypeFactory <Catalog> .TryCreateInstance()), EntryState.Modified)); modifiedEntity.Patch(originalEntity); } else { repository.Add(modifiedEntity); changedEntries.Add(new GenericChangedEntry <Catalog>(catalog, EntryState.Added)); } } //Raise domain events await _eventPublisher.Publish(new CatalogChangingEvent(changedEntries)); //Save changes in database await repository.UnitOfWork.CommitAsync(); pkMap.ResolvePrimaryKeys(); //Reset cached catalogs and catalogs CatalogCacheRegion.ExpireRegion(); await _eventPublisher.Publish(new CatalogChangedEvent(changedEntries)); } }
public virtual async Task SaveChangesAsync(Category[] categories) { var pkMap = new PrimaryKeyResolvingMap(); var changedEntries = new List <GenericChangedEntry <Category> >(); await ValidateCategoryPropertiesAsync(categories); using (var repository = _repositoryFactory()) { var dbExistCategories = await repository.GetCategoriesByIdsAsync(categories.Where(x => !x.IsTransient()).Select(x => x.Id).ToArray(), CategoryResponseGroup.Full); foreach (var category in categories) { var originalEntity = dbExistCategories.FirstOrDefault(x => x.Id == category.Id); var modifiedEntity = AbstractTypeFactory <CategoryEntity> .TryCreateInstance().FromModel(category, pkMap); if (originalEntity != null) { changedEntries.Add(new GenericChangedEntry <Category>(category, originalEntity.ToModel(AbstractTypeFactory <Category> .TryCreateInstance()), EntryState.Modified)); modifiedEntity.Patch(originalEntity); //Force set ModifiedDate property to mark a product changed. Special for partial update cases when product table not have changes originalEntity.ModifiedDate = DateTime.UtcNow; } else { repository.Add(modifiedEntity); changedEntries.Add(new GenericChangedEntry <Category>(category, EntryState.Added)); } } await _eventPublisher.Publish(new CategoryChangingEvent(changedEntries)); await repository.UnitOfWork.CommitAsync(); pkMap.ResolvePrimaryKeys(); CatalogCacheRegion.ExpireRegion(); await _eventPublisher.Publish(new CategoryChangedEvent(changedEntries)); } }
public Task <PropertyDictionaryItem[]> GetByIdsAsync(string[] ids) { var cacheKey = CacheKey.With(GetType(), "GetByIdsAsync", string.Join(",", ids)); return(_platformMemoryCache.GetOrCreateExclusive(cacheKey, async(cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(DictionaryItemsCacheRegion.CreateChangeToken()); PropertyDictionaryItem[] result; using (var repository = _repositoryFactory()) { //Optimize performance and CPU usage repository.DisableChangesTracking(); result = (await repository.GetPropertyDictionaryItemsByIdsAsync(ids)) .Select(x => x.ToModel(AbstractTypeFactory <PropertyDictionaryItem> .TryCreateInstance())) .ToArray(); } return result; })); }
protected virtual IDictionary <string, Property> PreloadAllProperties() { var cacheKey = CacheKey.With(GetType(), "PreloadAllProperties"); return(_memoryCache.GetOrCreateExclusive(cacheKey, (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); using (var repository = _repositoryFactory()) { repository.DisableChangesTracking(); var propertyIds = repository.Properties.Select(p => p.Id).ToArray(); var entities = repository.GetPropertiesByIds(propertyIds); var properties = entities.Select(p => p.ToModel(AbstractTypeFactory <Property> .TryCreateInstance())).ToArray(); LoadDependencies(properties); ApplyInheritanceRules(properties); var result = properties.ToDictionary(p => p.Id, StringComparer.OrdinalIgnoreCase); return result; } })); }
protected virtual async Task <Property[]> PreloadAllCatalogPropertiesAsync(string catalogId) { var cacheKey = CacheKey.With(GetType(), "PreloadAllCatalogProperties", catalogId); return(await _platformMemoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); using (var repository = _repositoryFactory()) { repository.DisableChangesTracking(); var result = (await repository.GetAllCatalogPropertiesAsync(catalogId)) .GroupBy(p => p.Id, StringComparer.OrdinalIgnoreCase) // Remove duplicates .Select(g => g.First()) .OrderBy(p => p.Name, StringComparer.OrdinalIgnoreCase) .Select(p => p.ToModel(AbstractTypeFactory <Property> .TryCreateInstance())) .ToArray(); return result; } })); }
public async Task <ProductPart[]> GetProductPartsAsync(string productId) { var workContext = _workContextAccessor.WorkContext; var cacheKey = CacheKey.With(GetType(), nameof(GetProductPartsAsync), productId); var searchResult = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(_apiChangesWatcher.CreateChangeToken()); var searchPartsResultDto = await _demoCatalogApi.SearchAsync(new DemoProductPartSearchCriteria { ConfiguredProductId = productId, Take = int.MaxValue }); return(searchPartsResultDto); }); var partItemIds = searchResult.Results? .Where(x => x.PartItems != null).SelectMany(x => x.PartItems).Select(x => x.ItemId).Distinct() .ToArray(); var allPartItems = !partItemIds.IsNullOrEmpty() ? await GetProductsAsync(partItemIds) : null; // Potential recursion ProductPart ConvertDtoToProductPartAndAttachItsItems(DemoProductPart x, WorkContext workContext, Product[] allPartItems) { var productPart = x.ToProductPart(workContext.CurrentLanguage.CultureName); productPart.Items = x.PartItems? .OrderBy(partItemInfo => partItemInfo.Priority) .Select(partItemInfo => allPartItems?.FirstOrDefault(product => product.Id.EqualsInvariant(partItemInfo.ItemId))) .Where(product => product != null) .ToArray() ?? Array.Empty <Product>(); return(productPart); } var productParts = searchResult.Results?.OrderBy(x => x.Priority).Select(x => ConvertDtoToProductPartAndAttachItsItems(x, workContext, allPartItems)) .ToArray <ProductPart>() ?? Array.Empty <ProductPart>(); return(productParts); }
private async Task <IPagedList <Category> > InnerSearchCategoriesAsync(CategorySearchCriteria criteria, WorkContext workContext) { var cacheKey = CacheKey.With(GetType(), "InnerSearchCategoriesAsync", criteria.GetCacheKey(), workContext.CurrentStore.Id, workContext.CurrentLanguage.CultureName, workContext.CurrentCurrency.Code); var searchResult = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(_apiChangesWatcher.CreateChangeToken()); criteria = criteria.Clone(); var searchCriteria = criteria.ToCategorySearchCriteriaDto(workContext); return(await _searchApi.SearchCategoriesAsync(searchCriteria)); }); var result = new PagedList <Category>(new List <Category>().AsQueryable(), 1, 1); if (searchResult.Items != null) { result = new PagedList <Category>(searchResult.Items.Select(x => x.ToCategory(workContext.CurrentLanguage, workContext.CurrentStore)).AsQueryable(), criteria.PageNumber, criteria.PageSize); } //Set lazy loading for child categories SetChildCategoriesLazyLoading(result.ToArray()); return(result); }
/// <summary> /// Async search categories by given criteria /// </summary> /// <param name="criteria"></param> /// <returns></returns> public virtual async Task <IPagedList <Category> > SearchCategoriesAsync(CategorySearchCriteria criteria) { var workContext = _workContextAccessor.WorkContext; var cacheKey = CacheKey.With(GetType(), nameof(SearchCategoriesAsync), criteria.GetCacheKey(), workContext.CurrentStore.Id, workContext.CurrentLanguage.CultureName, workContext.CurrentCurrency.Code); var searchResult = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) => { cacheEntry.AddExpirationToken(CatalogCacheRegion.CreateChangeToken()); cacheEntry.AddExpirationToken(_apiChangesWatcher.CreateChangeToken()); criteria = criteria.Clone() as CategorySearchCriteria; var searchCriteria = criteria.ToCategorySearchCriteriaDto(workContext); return(await _searchApi.SearchCategoriesAsync(searchCriteria)); }); var result = new PagedList <Category>(new List <Category>().AsQueryable(), 1, 1); if (searchResult.Items != null) { result = new PagedList <Category>(searchResult.Items.Select(x => x.ToCategory(workContext.CurrentLanguage, workContext.CurrentStore)).AsQueryable(), criteria.PageNumber, criteria.PageSize); } //Set lazy loading for child categories EstablishLazyDependenciesForCategories(result.ToArray()); return(result); }
protected virtual void ClearCache(IEnumerable <Category> categories) { CatalogCacheRegion.ExpireRegion(); SeoInfoCacheRegion.ExpireRegion(); }