Skip to content

Commit

Permalink
Merge branch 'master' into Removing-unused-directives
Browse files Browse the repository at this point in the history
  • Loading branch information
hemantkd committed Nov 19, 2018
2 parents 6299d5c + 04530db commit 218c832
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 46 deletions.
5 changes: 3 additions & 2 deletions src/ApplicationCore/Interfaces/IAsyncRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ namespace Microsoft.eShopWeb.ApplicationCore.Interfaces
public interface IAsyncRepository<T> where T : BaseEntity
{
Task<T> GetByIdAsync(int id);
Task<List<T>> ListAllAsync();
Task<List<T>> ListAsync(ISpecification<T> spec);
Task<IReadOnlyList<T>> ListAllAsync();
Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec);
Task<T> AddAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(T entity);
Task<int> CountAsync(ISpecification<T> spec);
}
}
1 change: 1 addition & 0 deletions src/ApplicationCore/Interfaces/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public interface IRepository<T> where T : BaseEntity
T Add(T entity);
void Update(T entity);
void Delete(T entity);
int Count(ISpecification<T> spec);
}
}
6 changes: 6 additions & 0 deletions src/ApplicationCore/Interfaces/ISpecification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,11 @@ public interface ISpecification<T>
Expression<Func<T, bool>> Criteria { get; }
List<Expression<Func<T, object>>> Includes { get; }
List<string> IncludeStrings { get; }
Expression<Func<T, object>> OrderBy { get; }
Expression<Func<T, object>> OrderByDescending { get; }

int Take { get; }
int Skip { get; }
bool isPagingEnabled { get;}
}
}
20 changes: 20 additions & 0 deletions src/ApplicationCore/Specifications/BaseSpecification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ protected BaseSpecification(Expression<Func<T, bool>> 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>();
public Expression<Func<T, object>> OrderBy { get; private set; }
public Expression<Func<T, object>> OrderByDescending { get; private set; }

public int Take { get; private set; }
public int Skip { get; private set; }
public bool isPagingEnabled { get; private set; } = false;

protected virtual void AddInclude(Expression<Func<T, object>> includeExpression)
{
Expand All @@ -23,5 +29,19 @@ protected virtual void AddInclude(string includeString)
{
IncludeStrings.Add(includeString);
}
protected virtual void ApplyPaging(int skip, int take)
{
Skip = skip;
Take = take;
isPagingEnabled = true;
}
protected virtual void ApplyOrderBy(Expression<Func<T, object>> orderByExpression)
{
OrderBy = orderByExpression;
}
protected virtual void ApplyOrderByDescending(Expression<Func<T, object>> orderByDescendingExpression)
{
OrderByDescending = orderByDescendingExpression;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.eShopWeb.ApplicationCore.Entities;

namespace Microsoft.eShopWeb.ApplicationCore.Specifications
{
public class CatalogFilterPaginatedSpecification : BaseSpecification<CatalogItem>
{
public CatalogFilterPaginatedSpecification(int skip, int take, int? brandId, int? typeId)
: base(i => (!brandId.HasValue || i.CatalogBrandId == brandId) &&
(!typeId.HasValue || i.CatalogTypeId == typeId))
{
ApplyPaging(skip, take);
}
}
}
46 changes: 16 additions & 30 deletions src/Infrastructure/Data/EfRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public EfRepository(CatalogContext dbContext)
{
_dbContext = dbContext;
}
private IQueryable<T> ApplySpecification(ISpecification<T> spec)
{
return SpecificationEvaluator<T>.GetQuery(_dbContext.Set<T>().AsQueryable(), spec);
}

public virtual T GetById(int id)
{
Expand All @@ -42,44 +46,26 @@ public IEnumerable<T> ListAll()
return _dbContext.Set<T>().AsEnumerable();
}

public async Task<List<T>> ListAllAsync()
public async Task<IReadOnlyList<T>> ListAllAsync()
{
return await _dbContext.Set<T>().ToListAsync();
}

public IEnumerable<T> List(ISpecification<T> spec)
{
// fetch a Queryable that includes all expression-based includes
var queryableResultWithIncludes = spec.Includes
.Aggregate(_dbContext.Set<T>().AsQueryable(),
(current, include) => current.Include(include));

// modify the IQueryable to include any string-based include statements
var secondaryResult = spec.IncludeStrings
.Aggregate(queryableResultWithIncludes,
(current, include) => current.Include(include));

// return the result of the query using the specification's criteria expression
return secondaryResult
.Where(spec.Criteria)
.AsEnumerable();
return ApplySpecification(spec).AsEnumerable();
}
public async Task<List<T>> ListAsync(ISpecification<T> spec)
public async Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec)
{
// fetch a Queryable that includes all expression-based includes
var queryableResultWithIncludes = spec.Includes
.Aggregate(_dbContext.Set<T>().AsQueryable(),
(current, include) => current.Include(include));

// modify the IQueryable to include any string-based include statements
var secondaryResult = spec.IncludeStrings
.Aggregate(queryableResultWithIncludes,
(current, include) => current.Include(include));

// return the result of the query using the specification's criteria expression
return await secondaryResult
.Where(spec.Criteria)
.ToListAsync();
return await ApplySpecification(spec).ToListAsync();
}
public int Count(ISpecification<T> spec)
{
return ApplySpecification(spec).Count();
}
public async Task<int> CountAsync(ISpecification<T> spec)
{
return await ApplySpecification(spec).CountAsync();
}

public T Add(T entity)
Expand Down
44 changes: 44 additions & 0 deletions src/Infrastructure/Data/SpecificationEvaluator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Microsoft.eShopWeb.Infrastructure.Data
{
public class SpecificationEvaluator<T> where T : BaseEntity
{
public static IQueryable<T> GetQuery(IQueryable<T> inputQuery, ISpecification<T> specification)
{
var query = inputQuery;

// modify the IQueryable using the specification's criteria expression
if (specification.Criteria != null)
query = query.Where(specification.Criteria);

// Includes all expression-based includes
query = specification.Includes.Aggregate(query,
(current, include) => current.Include(include));

// Include any string-based include statements
query = specification.IncludeStrings.Aggregate(query,
(current, include) => current.Include(include));

// Apply ordering if expressions are set
if (specification.OrderBy != null)
query = query.OrderBy(specification.OrderBy);
else if (specification.OrderByDescending != null)
query = query.OrderByDescending(specification.OrderByDescending);

// Apply paging if enabled
if (specification.isPagingEnabled)
{
query = query.Skip(specification.Skip)
.Take(specification.Take);
}
return query;
}
}
}
File renamed without changes.
12 changes: 5 additions & 7 deletions src/Web/Services/CatalogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@ public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int item
_logger.LogInformation("GetCatalogItems called.");

var filterSpecification = new CatalogFilterSpecification(brandId, typeId);
var root = _itemRepository.List(filterSpecification);
var filterPaginatedSpecification =
new CatalogFilterPaginatedSpecification(itemsPage * pageIndex, itemsPage, brandId, typeId);

var totalItems = root.Count();

var itemsOnPage = root
.Skip(itemsPage * pageIndex)
.Take(itemsPage)
.ToList();
// the implementation below using ForEach and Count. We need a List.
var itemsOnPage = _itemRepository.List(filterPaginatedSpecification).ToList();
var totalItems = _itemRepository.Count(filterSpecification);

itemsOnPage.ForEach(x =>
{
Expand Down
12 changes: 5 additions & 7 deletions src/WebRazorPages/Services/CatalogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,12 @@ public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int item
_logger.LogInformation("GetCatalogItems called.");

var filterSpecification = new CatalogFilterSpecification(brandId, typeId);
var root = _itemRepository.List(filterSpecification);
var filterPaginatedSpecification =
new CatalogFilterPaginatedSpecification(itemsPage * pageIndex, itemsPage, brandId, typeId);

var totalItems = root.Count();

var itemsOnPage = root
.Skip(itemsPage * pageIndex)
.Take(itemsPage)
.ToList();
// the implementation below using ForEach and Count. We need a List.
var itemsOnPage = _itemRepository.List(filterPaginatedSpecification).ToList();
var totalItems = _itemRepository.Count(filterSpecification);

itemsOnPage.ForEach(x =>
{
Expand Down

0 comments on commit 218c832

Please sign in to comment.