Skip to content

Commit 20b060a

Browse files
committed
Re-adding BasketQueryService
1 parent a675f3a commit 20b060a

File tree

6 files changed

+65
-23
lines changed

6 files changed

+65
-23
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.Threading.Tasks;
2+
3+
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces;
4+
5+
/// <summary>
6+
/// Specific query used to fetch count without running in memory
7+
/// </summary>
8+
public interface IBasketQueryService
9+
{
10+
Task<int> CountTotalBasketItems(string username);
11+
}
12+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Linq;
2+
using System.Threading.Tasks;
3+
using Microsoft.EntityFrameworkCore;
4+
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
5+
6+
namespace Microsoft.eShopWeb.Infrastructure.Data.Queries;
7+
8+
public class BasketQueryService : IBasketQueryService
9+
{
10+
private readonly CatalogContext _dbContext;
11+
12+
public BasketQueryService(CatalogContext dbContext)
13+
{
14+
_dbContext = dbContext;
15+
}
16+
17+
/// <summary>
18+
/// This method performs the sum on the database rather than in memory
19+
/// </summary>
20+
/// <param name="username"></param>
21+
/// <returns></returns>
22+
public async Task<int> CountTotalBasketItems(string username)
23+
{
24+
var totalItems = await _dbContext.Baskets
25+
.Where(basket => basket.BuyerId == username)
26+
.SelectMany(item => item.Items)
27+
.SumAsync(sum => sum.Quantity);
28+
29+
return totalItems;
30+
}
31+
}

src/Web/Configuration/ConfigureCoreServices.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
22
using Microsoft.eShopWeb.ApplicationCore.Services;
33
using Microsoft.eShopWeb.Infrastructure.Data;
4+
using Microsoft.eShopWeb.Infrastructure.Data.Queries;
45
using Microsoft.eShopWeb.Infrastructure.Logging;
56
using Microsoft.eShopWeb.Infrastructure.Services;
67
using Microsoft.Extensions.Configuration;
@@ -18,6 +19,7 @@ public static IServiceCollection AddCoreServices(this IServiceCollection service
1819

1920
services.AddScoped<IBasketService, BasketService>();
2021
services.AddScoped<IOrderService, OrderService>();
22+
services.AddScoped<IBasketQueryService, BasketQueryService>();
2123
services.AddSingleton<IUriComposer>(new UriComposer(configuration.Get<CatalogSettings>()));
2224
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
2325
services.AddTransient<IEmailSender, EmailSender>();

src/Web/Interfaces/IBasketViewModelService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ namespace Microsoft.eShopWeb.Web.Interfaces;
77
public interface IBasketViewModelService
88
{
99
Task<BasketViewModel> GetOrCreateBasketForUser(string userName);
10+
Task<int> CountTotalBasketItems(string username);
1011
Task<BasketViewModel> Map(Basket basket);
1112
}

src/Web/Pages/Shared/Components/BasketComponent/Basket.cs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,21 @@
22
using System.Threading.Tasks;
33
using Microsoft.AspNetCore.Identity;
44
using Microsoft.AspNetCore.Mvc;
5-
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
6-
using Microsoft.eShopWeb.ApplicationCore.Specifications;
75
using Microsoft.eShopWeb.Infrastructure.Identity;
86
using Microsoft.eShopWeb.Web.Interfaces;
97
using Microsoft.eShopWeb.Web.ViewModels;
10-
using BasketEntity = Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate.Basket;
118

129
namespace Microsoft.eShopWeb.Web.Pages.Shared.Components.BasketComponent;
1310

1411
public class Basket : ViewComponent
1512
{
16-
private readonly IBasketViewModelService _basketViewModelService;
17-
private readonly IReadRepository<BasketEntity> _basketRepository;
13+
private readonly IBasketViewModelService _basketService;
1814
private readonly SignInManager<ApplicationUser> _signInManager;
1915

20-
public Basket(IBasketViewModelService basketViewModelService,
21-
IReadRepository<BasketEntity> basketRepository,
22-
SignInManager<ApplicationUser> signInManager)
16+
public Basket(IBasketViewModelService basketService,
17+
SignInManager<ApplicationUser> signInManager)
2318
{
24-
_basketViewModelService = basketViewModelService;
25-
_basketRepository = basketRepository;
19+
_basketService = basketService;
2620
_signInManager = signInManager;
2721
}
2822

@@ -39,26 +33,18 @@ private async Task<int> CountTotalBasketItems()
3933
{
4034
if (_signInManager.IsSignedIn(HttpContext.User))
4135
{
42-
var userNameSpec = new BasketWithItemsSpecification(User.Identity.Name);
43-
44-
var userBasket = await _basketRepository.GetBySpecAsync(userNameSpec);
45-
if (userBasket == null) return 0;
46-
return userBasket.TotalItems;
36+
return await _basketService.CountTotalBasketItems(User.Identity.Name);
4737
}
4838

4939
string anonymousId = GetAnnonymousIdFromCookie();
5040
if (anonymousId == null)
5141
return 0;
5242

53-
var anonymousSpec = new BasketWithItemsSpecification(anonymousId);
54-
var anonymousBasket = await _basketRepository.GetBySpecAsync(anonymousSpec);
55-
if (anonymousBasket == null) return 0;
56-
return anonymousBasket.TotalItems;
43+
return await _basketService.CountTotalBasketItems(anonymousId);
5744
}
5845

5946
private string GetAnnonymousIdFromCookie()
6047
{
61-
// TODO: Add a prefix to anonymous cookie values so they cannot collide with user names
6248
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME))
6349
{
6450
var id = Request.Cookies[Constants.BASKET_COOKIENAME];

src/Web/Services/BasketViewModelService.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ public class BasketViewModelService : IBasketViewModelService
1414
{
1515
private readonly IRepository<Basket> _basketRepository;
1616
private readonly IUriComposer _uriComposer;
17-
private readonly IReadRepository<CatalogItem> _itemRepository;
17+
private readonly IBasketQueryService _basketQueryService;
18+
private readonly IRepository<CatalogItem> _itemRepository;
1819

1920
public BasketViewModelService(IRepository<Basket> basketRepository,
20-
IReadRepository<CatalogItem> itemRepository,
21-
IUriComposer uriComposer)
21+
IRepository<CatalogItem> itemRepository,
22+
IUriComposer uriComposer,
23+
IBasketQueryService basketQueryService)
2224
{
2325
_basketRepository = basketRepository;
2426
_uriComposer = uriComposer;
27+
_basketQueryService = basketQueryService;
2528
_itemRepository = itemRepository;
2629
}
2730

@@ -83,4 +86,11 @@ public async Task<BasketViewModel> Map(Basket basket)
8386
Items = await GetBasketItems(basket.Items)
8487
};
8588
}
89+
90+
public async Task<int> CountTotalBasketItems(string username)
91+
{
92+
var counter = await _basketQueryService.CountTotalBasketItems(username);
93+
94+
return counter;
95+
}
8696
}

0 commit comments

Comments
 (0)