Using Base Specification Class (#56)

* Ardalis/upgrade1 (#44)

* Upgrading to netcore 2.0
Updating repository to support async options and refactoring to use it.

* Starting work on tracking customer orders feature.

* Cleaning up some bugs
Working on basket view component implementation

* Fixing up styles, especially for basket in header.

* Adding Order Features (#47)

* Working on order model binding from checkout page - WIP

* Small layout tweaks (#43)

* Updating quantities implemented.

* Fixed basket widget count

* Order History (#49)

* working on creating and viewing orders.
* Working on wiring up listing of orders
* List orders page works as expected. Needed to support ThenInclude scenarios. Currently using strings.

* Remove non-icon basket link from header
Add comments to EF query logic

* Refactoring to use base specification type

* minor cleanup
This commit is contained in:
Steve Smith
2017-10-18 13:18:25 -04:00
committed by GitHub
parent d52dbb1915
commit 964173f277
7 changed files with 47 additions and 76 deletions

View File

@@ -9,6 +9,5 @@ namespace ApplicationCore.Interfaces
Expression<Func<T, bool>> Criteria { get; } Expression<Func<T, bool>> Criteria { get; }
List<Expression<Func<T, object>>> Includes { get; } List<Expression<Func<T, object>>> Includes { get; }
List<string> IncludeStrings { get; } List<string> IncludeStrings { get; }
void AddInclude(Expression<Func<T, object>> includeExpression);
} }
} }

View File

@@ -0,0 +1,27 @@
using ApplicationCore.Interfaces;
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace ApplicationCore.Specifications
{
public abstract class BaseSpecification<T> : ISpecification<T>
{
public BaseSpecification(Expression<Func<T, bool>> criteria)
{
Criteria = criteria;
}
public Expression<Func<T, bool>> Criteria { get; }
public List<Expression<Func<T, object>>> Includes { get; } = new List<Expression<Func<T, object>>>();
public List<string> IncludeStrings { get; } = new List<string>();
protected virtual void AddInclude(Expression<Func<T, object>> includeExpression)
{
Includes.Add(includeExpression);
}
protected virtual void AddInclude(string includeString)
{
IncludeStrings.Add(includeString);
}
}
}

View File

@@ -1,39 +1,18 @@
using ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Entities;
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using ApplicationCore.Entities.OrderAggregate;
namespace ApplicationCore.Specifications namespace ApplicationCore.Specifications
{ {
public class BasketWithItemsSpecification : ISpecification<Basket> public class BasketWithItemsSpecification : BaseSpecification<Basket>
{ {
public BasketWithItemsSpecification(int basketId) public BasketWithItemsSpecification(int basketId)
:base(b => b.Id == basketId)
{ {
BasketId = basketId;
AddInclude(b => b.Items); AddInclude(b => b.Items);
} }
public BasketWithItemsSpecification(string buyerId) public BasketWithItemsSpecification(string buyerId)
:base(b => b.BuyerId == buyerId)
{ {
BuyerId = buyerId;
AddInclude(b => b.Items); AddInclude(b => b.Items);
} }
public int? BasketId { get; }
public string BuyerId { get; }
public Expression<Func<Basket, bool>> Criteria => b =>
(BasketId.HasValue && b.Id == BasketId.Value)
|| (BuyerId != null && b.BuyerId == BuyerId);
public List<Expression<Func<Basket, object>>> Includes { get; } = new List<Expression<Func<Basket, object>>>();
public List<string> IncludeStrings { get; } = new List<string>();
public void AddInclude(Expression<Func<Basket, object>> includeExpression)
{
Includes.Add(includeExpression);
}
} }
} }

View File

@@ -1,34 +1,14 @@
using ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Entities;
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace ApplicationCore.Specifications namespace ApplicationCore.Specifications
{ {
public class CatalogFilterSpecification : ISpecification<CatalogItem> public class CatalogFilterSpecification : BaseSpecification<CatalogItem>
{ {
public CatalogFilterSpecification(int? brandId, int? typeId) public CatalogFilterSpecification(int? brandId, int? typeId)
: base(i => (!brandId.HasValue || i.CatalogBrandId == brandId) &&
(!typeId.HasValue || i.CatalogTypeId == typeId))
{ {
BrandId = brandId;
TypeId = typeId;
}
public int? BrandId { get; }
public int? TypeId { get; }
public Expression<Func<CatalogItem, bool>> Criteria =>
i => (!BrandId.HasValue || i.CatalogBrandId == BrandId) &&
(!TypeId.HasValue || i.CatalogTypeId == TypeId);
public List<Expression<Func<CatalogItem, object>>> Includes { get; } = new List<Expression<Func<CatalogItem, object>>>();
public List<string> IncludeStrings { get; } = new List<string>();
public void AddInclude(Expression<Func<CatalogItem, object>> includeExpression)
{
Includes.Add(includeExpression);
} }
} }
} }

View File

@@ -1,35 +1,14 @@
using ApplicationCore.Interfaces; using ApplicationCore.Entities.OrderAggregate;
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using ApplicationCore.Entities.OrderAggregate;
namespace ApplicationCore.Specifications namespace ApplicationCore.Specifications
{ {
public class CustomerOrdersWithItemsSpecification : ISpecification<Order> public class CustomerOrdersWithItemsSpecification : BaseSpecification<Order>
{ {
private readonly string _buyerId;
public CustomerOrdersWithItemsSpecification(string buyerId) public CustomerOrdersWithItemsSpecification(string buyerId)
: base(o => o.BuyerId == buyerId)
{ {
_buyerId = buyerId;
AddInclude(o => o.OrderItems); AddInclude(o => o.OrderItems);
AddInclude("OrderItems.ItemOrdered"); AddInclude("OrderItems.ItemOrdered");
} }
public Expression<Func<Order, bool>> Criteria => o => o.BuyerId == _buyerId;
public List<Expression<Func<Order, object>>> Includes { get; } = new List<Expression<Func<Order, object>>>();
public List<string> IncludeStrings { get; } = new List<string>();
public void AddInclude(Expression<Func<Order, object>> includeExpression)
{
Includes.Add(includeExpression);
}
public void AddInclude(string includeString)
{
IncludeStrings.Add(includeString);
}
} }
} }

View File

@@ -43,25 +43,34 @@ namespace Infrastructure.Data
public IEnumerable<T> List(ISpecification<T> spec) public IEnumerable<T> List(ISpecification<T> spec)
{ {
// fetch a Queryable that includes all expression-based includes
var queryableResultWithIncludes = spec.Includes var queryableResultWithIncludes = spec.Includes
.Aggregate(_dbContext.Set<T>().AsQueryable(), .Aggregate(_dbContext.Set<T>().AsQueryable(),
(current, include) => current.Include(include)); (current, include) => current.Include(include));
// modify the IQueryable to include any string-based include statements
var secondaryResult = spec.IncludeStrings var secondaryResult = spec.IncludeStrings
.Aggregate(queryableResultWithIncludes, .Aggregate(queryableResultWithIncludes,
(current, include) => current.Include(include)); (current, include) => current.Include(include));
// return the result of the query using the specification's criteria expression
return secondaryResult return secondaryResult
.Where(spec.Criteria) .Where(spec.Criteria)
.AsEnumerable(); .AsEnumerable();
} }
public async Task<List<T>> ListAsync(ISpecification<T> spec) public async Task<List<T>> ListAsync(ISpecification<T> spec)
{ {
// fetch a Queryable that includes all expression-based includes
var queryableResultWithIncludes = spec.Includes var queryableResultWithIncludes = spec.Includes
.Aggregate(_dbContext.Set<T>().AsQueryable(), .Aggregate(_dbContext.Set<T>().AsQueryable(),
(current, include) => current.Include(include)); (current, include) => current.Include(include));
// modify the IQueryable to include any string-based include statements
var secondaryResult = spec.IncludeStrings var secondaryResult = spec.IncludeStrings
.Aggregate(queryableResultWithIncludes, .Aggregate(queryableResultWithIncludes,
(current, include) => current.Include(include)); (current, include) => current.Include(include));
// return the result of the query using the specification's criteria expression
return await secondaryResult return await secondaryResult
.Where(spec.Criteria) .Where(spec.Criteria)
.ToListAsync(); .ToListAsync();

View File

@@ -33,8 +33,6 @@
</a> </a>
</section> </section>
@await Html.PartialAsync("_LoginPartial") @await Html.PartialAsync("_LoginPartial")
<section class="col-lg-1 col-md-3 col-xs-6"><a asp-controller="Basket" asp-action="Index">Basket</a></section>
</article> </article>
</div> </div>
</header> </header>