Switching to NuGet Ardalis.Specifications (#389)
- updating to use Ardalis.Specifications package as it is maintained and has a more robust implementation - Removing all custom specification implementation - Updating unit tests
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ardalis.GuardClauses" Version="1.5.0" />
|
<PackageReference Include="Ardalis.GuardClauses" Version="1.5.0" />
|
||||||
|
<PackageReference Include="Ardalis.Specification" Version="3.0.0" />
|
||||||
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Helpers.Query
|
|
||||||
{
|
|
||||||
public class IncludeAggregator<TEntity>
|
|
||||||
{
|
|
||||||
public IncludeQuery<TEntity, TProperty> Include<TProperty>(Expression<Func<TEntity, TProperty>> selector)
|
|
||||||
{
|
|
||||||
var visitor = new IncludeVisitor();
|
|
||||||
visitor.Visit(selector);
|
|
||||||
|
|
||||||
var pathMap = new Dictionary<IIncludeQuery, string>();
|
|
||||||
var query = new IncludeQuery<TEntity, TProperty>(pathMap);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(visitor.Path))
|
|
||||||
{
|
|
||||||
pathMap[query] = visitor.Path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Helpers.Query
|
|
||||||
{
|
|
||||||
public class IncludeQuery<TEntity, TPreviousProperty> : IIncludeQuery<TEntity, TPreviousProperty>
|
|
||||||
{
|
|
||||||
public Dictionary<IIncludeQuery, string> PathMap { get; } = new Dictionary<IIncludeQuery, string>();
|
|
||||||
public IncludeVisitor Visitor { get; } = new IncludeVisitor();
|
|
||||||
|
|
||||||
public IncludeQuery(Dictionary<IIncludeQuery, string> pathMap)
|
|
||||||
{
|
|
||||||
PathMap = pathMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashSet<string> Paths => PathMap.Select(x => x.Value).ToHashSet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Helpers.Query
|
|
||||||
{
|
|
||||||
public static class IncludeQueryExtensions
|
|
||||||
{
|
|
||||||
public static IIncludeQuery<TEntity, TNewProperty> Include<TEntity, TPreviousProperty, TNewProperty>(
|
|
||||||
this IIncludeQuery<TEntity, TPreviousProperty> query,
|
|
||||||
Expression<Func<TEntity, TNewProperty>> selector)
|
|
||||||
{
|
|
||||||
query.Visitor.Visit(selector);
|
|
||||||
|
|
||||||
var includeQuery = new IncludeQuery<TEntity, TNewProperty>(query.PathMap);
|
|
||||||
query.PathMap[includeQuery] = query.Visitor.Path;
|
|
||||||
|
|
||||||
return includeQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IIncludeQuery<TEntity, TNewProperty> ThenInclude<TEntity, TPreviousProperty, TNewProperty>(
|
|
||||||
this IIncludeQuery<TEntity, TPreviousProperty> query,
|
|
||||||
Expression<Func<TPreviousProperty, TNewProperty>> selector)
|
|
||||||
{
|
|
||||||
query.Visitor.Visit(selector);
|
|
||||||
|
|
||||||
// If the visitor did not generated a path, return a new IncludeQuery with an unmodified PathMap.
|
|
||||||
if (string.IsNullOrEmpty(query.Visitor.Path))
|
|
||||||
{
|
|
||||||
return new IncludeQuery<TEntity, TNewProperty>(query.PathMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pathMap = query.PathMap;
|
|
||||||
var existingPath = pathMap[query];
|
|
||||||
pathMap.Remove(query);
|
|
||||||
|
|
||||||
var includeQuery = new IncludeQuery<TEntity, TNewProperty>(query.PathMap);
|
|
||||||
pathMap[includeQuery] = $"{existingPath}.{query.Visitor.Path}";
|
|
||||||
|
|
||||||
return includeQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IIncludeQuery<TEntity, TNewProperty> ThenInclude<TEntity, TPreviousProperty, TNewProperty>(
|
|
||||||
this IIncludeQuery<TEntity, IEnumerable<TPreviousProperty>> query,
|
|
||||||
Expression<Func<TPreviousProperty, TNewProperty>> selector)
|
|
||||||
{
|
|
||||||
query.Visitor.Visit(selector);
|
|
||||||
|
|
||||||
// If the visitor did not generated a path, return a new IncludeQuery with an unmodified PathMap.
|
|
||||||
if (string.IsNullOrEmpty(query.Visitor.Path))
|
|
||||||
{
|
|
||||||
return new IncludeQuery<TEntity, TNewProperty>(query.PathMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pathMap = query.PathMap;
|
|
||||||
var existingPath = pathMap[query];
|
|
||||||
pathMap.Remove(query);
|
|
||||||
|
|
||||||
var includeQuery = new IncludeQuery<TEntity, TNewProperty>(query.PathMap);
|
|
||||||
pathMap[includeQuery] = $"{existingPath}.{query.Visitor.Path}";
|
|
||||||
|
|
||||||
return includeQuery;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Helpers.Query
|
|
||||||
{
|
|
||||||
public class IncludeVisitor : ExpressionVisitor
|
|
||||||
{
|
|
||||||
public string Path { get; private set; } = string.Empty;
|
|
||||||
|
|
||||||
protected override Expression VisitMember(MemberExpression node)
|
|
||||||
{
|
|
||||||
Path = string.IsNullOrEmpty(Path) ? node.Member.Name : $"{node.Member.Name}.{Path}";
|
|
||||||
|
|
||||||
return base.VisitMember(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces
|
|
||||||
{
|
|
||||||
public interface IIncludeQuery
|
|
||||||
{
|
|
||||||
Dictionary<IIncludeQuery, string> PathMap { get; }
|
|
||||||
IncludeVisitor Visitor { get; }
|
|
||||||
HashSet<string> Paths { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IIncludeQuery<TEntity, out TPreviousProperty> : IIncludeQuery
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces
|
|
||||||
{
|
|
||||||
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; }
|
|
||||||
Expression<Func<T, object>> GroupBy { get; }
|
|
||||||
|
|
||||||
int Take { get; }
|
|
||||||
int Skip { get; }
|
|
||||||
bool IsPagingEnabled { get;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
using System;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
|
||||||
{
|
|
||||||
public abstract class BaseSpecification<T> : ISpecification<T>
|
|
||||||
{
|
|
||||||
protected 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>();
|
|
||||||
public Expression<Func<T, object>> OrderBy { get; private set; }
|
|
||||||
public Expression<Func<T, object>> OrderByDescending { get; private set; }
|
|
||||||
public Expression<Func<T, object>> GroupBy { 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)
|
|
||||||
{
|
|
||||||
Includes.Add(includeExpression);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddIncludes<TProperty>(Func<IncludeAggregator<T>, IIncludeQuery<T, TProperty>> includeGenerator)
|
|
||||||
{
|
|
||||||
var includeQuery = includeGenerator(new IncludeAggregator<T>());
|
|
||||||
IncludeStrings.AddRange(includeQuery.Paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Not used anywhere at the moment, but someone requested an example of setting this up.
|
|
||||||
protected virtual void ApplyGroupBy(Expression<Func<T, object>> groupByExpression)
|
|
||||||
{
|
|
||||||
GroupBy = groupByExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
||||||
{
|
{
|
||||||
public sealed class BasketWithItemsSpecification : BaseSpecification<Basket>
|
public sealed class BasketWithItemsSpecification : BaseSpecification<Basket>
|
||||||
{
|
{
|
||||||
public BasketWithItemsSpecification(int basketId)
|
public BasketWithItemsSpecification(int basketId) : base(b => b.Id == basketId)
|
||||||
:base(b => b.Id == basketId)
|
|
||||||
{
|
{
|
||||||
AddInclude(b => b.Items);
|
AddInclude(b => b.Items);
|
||||||
}
|
}
|
||||||
public BasketWithItemsSpecification(string buyerId)
|
public BasketWithItemsSpecification(string buyerId) : base(b => b.BuyerId == buyerId)
|
||||||
:base(b => b.BuyerId == buyerId)
|
|
||||||
{
|
{
|
||||||
AddInclude(b => b.Items);
|
AddInclude(b => b.Items);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
using Ardalis.Specification;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
using Ardalis.Specification.QueryExtensions.Include;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
||||||
{
|
{
|
||||||
@@ -8,7 +9,8 @@ namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
|||||||
public CustomerOrdersWithItemsSpecification(string buyerId)
|
public CustomerOrdersWithItemsSpecification(string buyerId)
|
||||||
: base(o => o.BuyerId == buyerId)
|
: base(o => o.BuyerId == buyerId)
|
||||||
{
|
{
|
||||||
AddIncludes(query => query.Include(o => o.OrderItems).ThenInclude(i => i.ItemOrdered));
|
AddIncludes(query => query.Include(o => o.OrderItems)
|
||||||
|
.ThenInclude(i => i.ItemOrdered));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -33,12 +34,14 @@ namespace Microsoft.eShopWeb.Infrastructure.Data
|
|||||||
|
|
||||||
public async Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec)
|
public async Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec)
|
||||||
{
|
{
|
||||||
return await ApplySpecification(spec).ToListAsync();
|
var specificationResult = await ApplySpecification(spec);
|
||||||
|
return await specificationResult.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> CountAsync(ISpecification<T> spec)
|
public async Task<int> CountAsync(ISpecification<T> spec)
|
||||||
{
|
{
|
||||||
return await ApplySpecification(spec).CountAsync();
|
var specificationResult = await ApplySpecification(spec);
|
||||||
|
return await specificationResult.CountAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<T> AddAsync(T entity)
|
public async Task<T> AddAsync(T entity)
|
||||||
@@ -63,17 +66,19 @@ namespace Microsoft.eShopWeb.Infrastructure.Data
|
|||||||
|
|
||||||
public async Task<T> FirstAsync(ISpecification<T> spec)
|
public async Task<T> FirstAsync(ISpecification<T> spec)
|
||||||
{
|
{
|
||||||
return await ApplySpecification(spec).FirstAsync();
|
var specificationResult = await ApplySpecification(spec);
|
||||||
|
return await specificationResult.FirstAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<T> FirstOrDefaultAsync(ISpecification<T> spec)
|
public async Task<T> FirstOrDefaultAsync(ISpecification<T> spec)
|
||||||
{
|
{
|
||||||
return await ApplySpecification(spec).FirstOrDefaultAsync();
|
var specificationResult = await ApplySpecification(spec);
|
||||||
|
return await specificationResult.FirstOrDefaultAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQueryable<T> ApplySpecification(ISpecification<T> spec)
|
private async Task<IQueryable<T>> ApplySpecification(ISpecification<T> spec)
|
||||||
{
|
{
|
||||||
return SpecificationEvaluator<T>.GetQuery(_dbContext.Set<T>().AsQueryable(), spec);
|
return await EfSpecificationEvaluator<T>.GetQuery(_dbContext.Set<T>().AsQueryable(), spec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Ardalis.Specification;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Infrastructure.Data
|
namespace Microsoft.eShopWeb.Infrastructure.Data
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (specification.GroupBy != null)
|
|
||||||
{
|
|
||||||
query = query.GroupBy(specification.GroupBy).SelectMany(x => x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply paging if enabled
|
|
||||||
if (specification.IsPagingEnabled)
|
|
||||||
{
|
|
||||||
query = query.Skip(specification.Skip)
|
|
||||||
.Take(specification.Take);
|
|
||||||
}
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ardalis.EFCore.Extensions" Version="1.1.0" />
|
<PackageReference Include="Ardalis.EFCore.Extensions" Version="1.1.0" />
|
||||||
|
<PackageReference Include="Ardalis.Specification" Version="3.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.4" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.4" />
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ardalis.ListStartupServices" Version="1.1.3" />
|
<PackageReference Include="Ardalis.ListStartupServices" Version="1.1.3" />
|
||||||
|
<PackageReference Include="Ardalis.Specification" Version="3.0.0" />
|
||||||
|
|
||||||
<PackageReference Include="MediatR" Version="8.0.1" />
|
<PackageReference Include="MediatR" Version="8.0.1" />
|
||||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.0.0" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
using Ardalis.Specification.QueryExtensions.Include;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Helpers.Query.IncludeAggregatorTests
|
namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Helpers.Query.IncludeAggregatorTests
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
using Ardalis.Specification.QueryExtensions.Include;
|
||||||
using Microsoft.eShopWeb.UnitTests.Builders;
|
using Microsoft.eShopWeb.UnitTests.Builders;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
using Ardalis.Specification.QueryExtensions.Include;
|
||||||
using Microsoft.eShopWeb.UnitTests.Builders;
|
using Microsoft.eShopWeb.UnitTests.Builders;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
using Ardalis.Specification.QueryExtensions.Include;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Microsoft.eShopWeb.UnitTests
|
|||||||
|
|
||||||
var result = GetTestBasketCollection()
|
var result = GetTestBasketCollection()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.FirstOrDefault(spec.Criteria);
|
.FirstOrDefault(spec.Criterias.FirstOrDefault());
|
||||||
|
|
||||||
Assert.NotNull(result);
|
Assert.NotNull(result);
|
||||||
Assert.Equal(_testBasketId, result.Id);
|
Assert.Equal(_testBasketId, result.Id);
|
||||||
@@ -34,7 +34,7 @@ namespace Microsoft.eShopWeb.UnitTests
|
|||||||
|
|
||||||
Assert.False(GetTestBasketCollection()
|
Assert.False(GetTestBasketCollection()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Any(spec.Criteria));
|
.Any(spec.Criterias.FirstOrDefault()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Basket> GetTestBasketCollection()
|
public List<Basket> GetTestBasketCollection()
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Microsoft.eShopWeb.ApplicationCore.Entities;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Moq;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.UnitTests
|
namespace Microsoft.eShopWeb.UnitTests
|
||||||
{
|
{
|
||||||
@@ -23,7 +22,7 @@ namespace Microsoft.eShopWeb.UnitTests
|
|||||||
|
|
||||||
var result = GetTestItemCollection()
|
var result = GetTestItemCollection()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(spec.Criteria);
|
.Where(spec.Criterias.FirstOrDefault());
|
||||||
|
|
||||||
Assert.Equal(expectedCount, result.Count());
|
Assert.Equal(expectedCount, result.Count());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Helpers.Query;
|
using Ardalis.Specification.QueryExtensions.Include;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
using Microsoft.eShopWeb.UnitTests.ApplicationCore.Helpers.Query;
|
using Microsoft.eShopWeb.UnitTests.ApplicationCore.Helpers.Query;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.UnitTests.Builders
|
namespace Microsoft.eShopWeb.UnitTests.Builders
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||||
using Microsoft.eShopWeb.Web.Features.MyOrders;
|
using Microsoft.eShopWeb.Web.Features.MyOrders;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
using Ardalis.Specification;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||||
using Microsoft.eShopWeb.Web.Features.OrderDetails;
|
using Microsoft.eShopWeb.Web.Features.OrderDetails;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|||||||
Reference in New Issue
Block a user