What is Design Pattern
Specification Design Pattern
Specification Pattern and Dynamic Query Building
ุชุนุฑูู ุงูู ุดููุฉ:
- ู
ุดุงูู Include:
- ุงูุฎุฑู ูู Open/Closed Principle:
ุนูุฏ ุฅุถุงูุฉ ู ูุฏูู ุฌุฏูุฏ (ู ุซู Brand ุฃู Category)ุ ุชุญุชุงุฌ ุชุนุฏูู ุงูููุฏ ูุฅุถุงูุฉ Includes ุฌุฏูุฏุฉุ ู ุง ูุฎุงูู ู ุจุฏุฃ Closed for Modifications. ููุง ุงุชููู ูุง ุนููุง (Open-Closed Principle) ุดูููุง ุงูู ุดููุฉ ุฏู ูู ุงูู Include - ุฃุฏุงุก ุบูุฑ ูุนุงู:
ุงุณุชุฎุฏุงู Where ุจุฏูุงู ู ู Find ูุคุฏู ุฅูู ุงุณุชุนูุงู ุงุช ุบูุฑ ู ุญุณูุฉุ ูุฃู Where ุชุนู ู ุนูู ุงูุจูุงูุงุช ู ุจุงุดุฑุฉ ู ู ูุงุนุฏุฉ ุงูุจูุงูุงุชุ ุจููู ุง Find ุชุจุฏุฃ ุจุงูุจุญุซ ู ุญูููุง (Local) ุซู ุชูุชูู ุฅูู Remote ูุชุญุณูู ุงูุฃุฏุงุก. ุดูููุง ุงูู ุดููุฉ ุฏู ูู ุงูุชุนุงู ู ู ุน Null ูู Brand ู Category
- ุงูุฎุฑู ูู Open/Closed Principle:
- ุงูุญู:
- ุงุณุชุฎุฏุงู Specification Pattern ูุจูุงุก ุงูุงุณุชุนูุงู ุงุช ุจุดูู ุฏููุงู ููู ุฏูู ุงูุญุงุฌุฉ ูุชุนุฏูู ุงูููุฏ ุนูุฏ ุฅุถุงูุฉ ู ูููุงุช ุฌุฏูุฏุฉ.
Specification Pattern
- ู ุด ู ู ุถู ู ุงูู 23 ุงููู ููููุง ุนูููู ูู ุงูู What is Design Pattern
ุงูููุฑุฉ ุงูุฑุฆูุณูุฉ:
- ุงููSpecification ูุนุงู ู ูู ุฌุฒุก ู ู ุงูุงุณุชุนูุงู ูู ุฎุงุตูุฉ (Specification).
- ุจูุงุก Method ุชุฃุฎุฐ ุงูู ุนุงููุฑ ุงูู ุทููุจุฉ ูุชููุดุฆ ุงูุงุณุชุนูุงู ุจุดูู ุฏููุงู ููู.
- ุจูุณุงุนุฏูู ุงูู ุฃุจูู ุงูู Query ุจุดูู Dynamicุ ูุฃูุง ุจูุณู ุงูู Query ุจุชุงุนู ูุฃุฌุฒุงุก ูุจุบูุฑูุง ูู ู ุฑุฉ ุนูู ุญุณุจ ุงูู Business
ุฎุทูุงุช ุจูุงุก Specification Pattern
1. ุฅูุดุงุก Interface ููู Specification:
- ููุฑูุญ ูุจุฑูุฌูุช ุงูู Core
- ููุนู ู ูููุฏุฑ ูุณู ูู Specifications
- ููุนู
ู ุฌูุงู Interface ุงุณู
ู
ISpecification
- ูููู Public ููููู Generic
- ูุชุญุท Constrain ุงููุง ูุงุฒู
ุชููู
BaseEntity
- ูุญุชูู ุนูู (Signatures) ููู Property ุชู ุซู ุฌุฒุก ู ู ุงูุงุณุชุนูุงู .
- ูุฑูุญ ูุดูู ุงูู Query ุงููู ููุช ุนู ูุชูุง Static ููุง ุงูุชุนุงู ู ู ุน Null ูู Brand ู Category
- ูููุงูู ุจูุชูุฑุฑ where ู Includes
- ุงูุฌุฒุก ุงููู ูุงูุขุฎุฑ ุจุชุงุน
FirstOrDefaultAsync
ูToListAsync
ุฏุง ุจูุชุบูุฑ ูู ุด ูููุชุจู ูููุชุจู ุจุนุฏูุง - ู
ู
ูู ุชููู ู
ููุด where ูู ุงูู
GetAll
ูุฃูู ู ู ูู ุฃุณุชุฎุฏู ูุง ุจุนุฏ ูุฏุง ูู ุนุงูุฒ ุฃุธูุฑ ูู ุงูุจุฑุงูุฏ ุฃู ุงููุงุชูุฌูุฑู (ูู ุงูู Filters ุนู ูู ูุง) - ุงูู
FirstOrDefault
ุจูุฎููุง ุงูู Query ูุชุนู ููุง Immediate Execution- Three Categories for Immediate (Element Operators - Casting Operator - Aggregation Operator)
public interface ISpecification<T> where T : BaseEntity
{
// ุฏู ุงููู ูุจุนุชูุง ููููุฑ
Expression<Func<T, bool>> Criteria { get; set;}
List<Expression<Func<T, object>>> Includes { get; set; }
}
- ุจูุงุฎุฏูุง Cs Delegates
- ุงูุงุชููู ุจูุนู ููุง Return ูููุจุนุฏ ุนู ุงูู Action ููุณุชุฎุฏู ุงูู Func
- ุงูุฃูู where ุจูุนู ู Return ูู True ุฃู False ูุจูุงุฎุฏ ุงูู Product ุจุชุงุนู ู ุซููุง
- ุงูู ุง ุงูุชุงูู ุจูุฑุฌุน ู ู ุงูู DB ูู ู ูู ุญุฑูููุง ูุฑุฌุน ุฃู ุญุงุฌุฉ ูุจูููู ุงูู ุจูุฑุฌุน object
2. ุฅูุดุงุก Class ูุชูููุฐ ุงูู Interface:
- ุงูููุงุณ ูุญู ู ุชูุงุตูู ุงูุงุณุชุนูุงู .
- ููุนู ูู ูู ุงูู Core ูู ูููุฏุฑ ุงูู Specifications ุจุฑุถู
- ู ู ูู ุฃุนู ููุง Full property ุนุงุฏู ูู ูุนู ู Validation ุฃู ูุฏุง ูุงุชููู ูุง ุนู ุงูู ูุถูุน ุฏุง ูู ุงูู Cs Properties
public static class BaseSpecifications<T> : ISpecification<T> where T : BaseEntity
{
public Expression<Func<T, bool>> Criteria { get; private set; }
public List<Expression<Func<T, object>>> Includes { get;} = new List<Expression<Func<T, object>>>();
public BaseSpecification()
{
}
public BaseSpecification(Expression<Func<T, bool>> criteria)
{
Criteria = criteria;
}
/*
public void AddInclude(Expression<Func<T, object>> includeExpression)
{
Includes.Add(includeExpression);
}
*/
}
- ูู ุง ูุนู ู ุงูู Method ูุจุชุงุฎุฏ ุงูุฅุชููู ุจุฑุงู ุชุฑ
- ูู ุงูู Method ูุชุนู ู Query ุชุฌูุจูู ูู ุงูู Products ูุจูุง ุงูู Criteria ุจูNull ุงูู ุง ูู ููุฌูุจ ุญุงุฌุงุช ู ุญุฏุฏุฉ ูุงูู ูุฑูุถ ุชุจูุง ุจู Expression
- ูุงููู ููุญุฏุฏ ุงูู Method
- ูุฃูุง ูุนู ู ุงุชููู Ctor ูุงุญุฏ ุจูุญุท ุงูู criteria ุจู Null ูุงูุชุงูู ุจูุญุทู ุจุงูู Expression
- ูู ุงูุนุงุฏู ูู ุนู ูุช Empty ctor ุงููู ุจูุญุตู ุงู ูู ุจูุญุท ูู ุงูู Properties ุจู Null ุฃู ุจุงูููู ุฉ ุงูู Default ุจุชุงุนูุงุ ูุงุญูุง ููุนู ู ูุงุญุฏ ููุนู ู Initialization ููู Includes ููุณูุจ ุงูู Criteria ุนุดุงู ุชูุถู ุจู Null
- ู ู ูู ูุญุทูุง ุจููู ุฉ ุนูู ุทูู ุจุฏู ู ุง ุฃุณุชูู ุงูู Ctor ูุชููุฐ
3. ุฅูุดุงุก Method ูุชุทุจูู ุงูู Specification:
- ููุนู ููุง ูู ุงูู Repository
- ูุญุชุงุฌ ุฃุนู
ู Class ุงุณู
ู
SpecificationEvaluator
ูุญุทูุชู ูู ุงูู Repository ุนุดุงู ุฃูุง ูุณุชุฎุฏู ู ู ุน ููุงุณ ุงูู Generic Repository - ุชุฃุฎุฐ:
- ุงููDbSet: ุงูุฌุฏูู ุงูุฐู ุชุนู ู ุนููู.
- ุงููSpecification Object: ุชูุงุตูู ุงูุงุณุชุนูุงู (Criteriaุ Includes).
internal static class SpecificationsEvaluator<T> where T : BaseEntity
public static IQueryable<T> GetQuery(IQueryable<T> inputQuery, ISpecification<T> spec)
{
var query = inputQuery;
// Apply Criteria
if (spec.Criteria != null)
{
query = query.Where(spec.Criteria);
}
// Apply Includes
query = spec.Includes.Aggregate(query, (currentQuery, includeExpression)
=> currentQuery.Include(includeExpression));
// query = _dbContext.Set<Product>().Where(P => P.Id==1)
// Includes
// 1. P => P.Brand
// 2. P => P.Category
// _dbContext.Set<Product>().Where(P => P.Id==1).Include(P => P.Brand)
// _dbContext.Set<Product>().Where(P => P.Id==1).Include(P => P.Brand).Include(P => P.Category)
return query;
}
Aggregate
ู ูุฌูุฏุฉ ูู ุงูู LINQ ูุดุฑุญูุง ููุง Cs Aggregate ุจูุนู ู Accumulate ููู ุงูู Includes ู ุน ุจุนุถ ูููุณุชุฎุฏู ุงูู Aggregate
string[] Names = {"Corn", "Pop"};
string Message = "Hello,";
Message = Names.Aggregate(Message, (x, y) => $"{x} {y}");
Console.WriteLine(Message);
ูู ูู ุงููู ููุนู ูู ุจุชุฏููู ุฃูู ููู ุฉ ุงููู ููุจูู ุนูููุง ุงููู ูู ููุง Message ูุจุนุฏูุง ุจุชุฏููู ุงูู Parameters ูุจูุจูุง ุฃูู Parameter ูู ุงูุฃูู ุงููู ูู ุฃูู ููู ุฉ ุนูุฏู ูุงูุชุงูู ุจูุงุฎุฏ ุฃูู ููู ุฉ ูู ุงูู Collection ุงููู ูุงุฏูุช ุจููุง ุงููู ูู ููุง ุงูู Names ูููุฐุง ูุญุฏ ู ุง ุชุฎูุต
4. ุงุณุชุฎุฏุงู ุงูู Method
- ููุง ุจูุญุท ู ุณูู ูู ุงูู Generic Repository ูู ุชูุชูุฑ ูู ุงูู Include
- ููุนู
ู ุงุชููู Method ุชุงูููู ูุงุญุฏ ุงุณู
ู
GetAllWithSpecAsync
ูุงูุชุงููGetWithSpecAsync
ููุญุทู ูู ุงูู Interface ู ุชูุณุงุด
Task<IEnumerable<T>> GetAllWithSpecAsync(ISpecifications<T> spec);
Task<T?> GetWithSpecAsync(ISpecifications<T> spec);
ูุจุนุฏูู ูุฑูุญ ุนูู Class ุงูู GenericRepository
ููุนู
ููู
Implement
public Task<IEnumerable<T>> GetAllWithSpecAsync(ISpecifications<T> spec)
{
return await SpecificationsEvaluator<T>.GetQuery(_dbContext.Set<T>(), spec).ToListAsync();
}
public Task<IEnumerable<T>> GetWithSpecAsync(ISpecifications<T> spec)
{
return await SpecificationsEvaluator<T>.GetQuery(_dbContext.Set<T>(), spec).FirstOrDefaultAsync();
}
ุจุณ ุงูุง ุนูุฏู ูุฏุง ุฌุฒุก ู
ุชูุฑุฑ ูู ุงูู GetAll
ูุงูู Get
ููุนู
ู Method Private
private IQueryable<T> ApplySpecifications(ISpecifications<T> spec)
{
return SpecificationsEvaluator<T>.GetQuery(_dbContext.Set<T>(), spec);
}
ููุบูุฑ ุจูุง ุงูู Methods ูุชุจูุง ูุฏุง
public Task<IEnumerable<T>> GetAllWithSpecAsync(ISpecifications<T> spec)
{
return await ApplySpecifications(spec).ToListAsync();
}