Get Products
كنا عملنا في الـ Specification Design Pattern
- محتاج أستخدمها مع الـ
GetAllWithSpecAsync
بس هي بتحتاج تاخدspec
- فهنحتاج نعمل object من الـ class اللي اسمه
BaseSpecifications
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
var spec = new BaseSpecifications<Product>();
var products = await _productsRepo.GetAllWithSpecAsync(spec);
return Ok(products)
}
نروح على Postman ونشوف الـ Collection اللي اسمه Session 02 ونغير الـ Variable بتاع الـ URL
هنلاقي فيه مشكلة ان دلوقتي بينادي على Specification والـ Criteria بـ Null ودا عادي بس المشكلة في الـ Includes هنلاقي ان الـ List فاضية وهنا المشكلة لأن المفروض يبقا فيها اتنين واحد للـ Brand وواحد للـ Category
فحل ممكن نعمله اننا نروح للـ ctor الفاضي ونضيف بايدينا الـ Expression
public BaseSpecification()
{
Includes.Add(P => P.Brand);
}
بس هيظهرلنا لأنه ميعرفش ايه الـ P دا لأننا عاملينها Generic فهو من النوع T وممكن الـ T تبقا أي حاجة من الـ Base Entity مش شرط Product ودا منطقي عشان لو حبينا نستخدمها مع باقي الحاجات
الحل
- هنعمل في الـ Core نعمل فولدر اسمه Specifications
- ونعمل للـ Product فولدر خاص بيه نسميه
ProductSpecs
- ونعمل Class نسميه
ProductWithBrandAndCategorySpecifications
- هيكون Public
- هيورث من الـ
BaseSpecifications
فهاخد منه الـ Properties - والـ Empty Ctor اللي هو هيعمل Chaining من الـ Empty بتاع الـ Base
- احنا جواه بقا نحط الـ Includes بتاعنا
public class ProductWithBrandAndCategorySpecifications : BaseSpecifications<Product>
{
public ProductWithBrandAndCategorySpecifications()
:base()
{
Includes.Add(P => P.Brand);
Includes.Add(P => P.Category);
}
}
- الـ Ctor دا هنستخدمه عشان
GetAll
- طيب لما هندخل على الـ Generic Repository ونشوف الـ
GetAllWithSpecAsync
فالسؤال المهم هو اتحدد امتا ان الـ T هو الـ Product؟ الإجابة هتكون هو من خلال الـ Ctor بتاع الـ Generic Repository اللي اتعمل في الـ Controller وكنا عملناه Ctor Injection فاتحدد من وقتها
في الآخر خالص هنستخدم الـ Spec المخصصة لـ Product دي في الـ Endpoint نفسها اللي هي GetAllWithSpecAsync
Get Product by ID
- هنروح في الـ Endpoint بتاعها ونستخدم الـ
GetWithSpecAsync
- هيقولي برضو انه محتاج
spec
فهنعمل Object منه ومحتاج نبعتله الـ ID
var spec = new ProductWithBrandAndCategorySpecifications(id);
var product = await _productRepo.GetWithSpecAsync();
- بس معنديش ctor بياخد Id فهحتاج أعمل واحد بياخد Id
- والفرق هنا انها مش هتعمل Chaining من Empty ctor انما هتعمل على اللي له Criteria عن طريق اني أمررلها الـ Expression بتاعتنا
public ProductWithBrandAndCategorySpecifications(int id)
:base(P => P.Id == id)
{
Includes.Add(P => P.Brand);
Includes.Add(P => P.Category);
}
ممكن السطرين بتوع الـ Includes دول بيتكرروا فنخليهم في Method عشان احنا مبنحبش التكرار ونسميها AddIncludes
شغل كل واحدة منهم واعمل Breakpoint على أول الـ Endpoint وتابع البروجكت وهو شغال