Introduction
ShopNest Product Management needs full CRUD — always use async methods in production (SaveChangesAsync, ToListAsync) to keep threads free under load.
After this article you will
- Create with AddAsync; read with FindAsync and LINQ
- Update tracked entities; implement soft delete
- Build ProductsController with five views
- Handle concurrency and errors in CRUD
Prerequisites
- Article 14 — EF Core Code First
- ShopNest.Web project from prior lessons
Concept deep-dive
// CREATE
await _db.Products.AddAsync(product);
await _db.SaveChangesAsync();
// READ
var product = await _db.Products.FindAsync(id);
var list = await _db.Products.Where(p => !p.IsDeleted).ToListAsync();
// UPDATE — entity tracked from query
product.Price = dto.Price;
await _db.SaveChangesAsync();
// SOFT DELETE
product.IsDeleted = true;
product.DeletedAt = DateTime.UtcNow;
await _db.SaveChangesAsync();
AsNoTracking() for read-only lists — better performance, no accidental updates.
Hands-on — ShopNest Product Management
- Product entity with IsDeleted flag.
- ProductsController: Index, Details, Create, Edit, Delete (soft).
- Try/catch DbUpdateException on duplicate SKU.
Common errors & best practices
- Sync SaveChanges on high traffic — blocks threads.
- Update detached entity — attach or use Update() carefully.
Interview questions
Q: Find vs FirstOrDefault?
A: Find uses PK cache first; FirstOrDefault runs query with any predicate.
Summary
- Always async CRUD in production ShopNest apps
- Soft delete preserves audit history
- AsNoTracking for read-only queries
Previous: EF Core Code First
Next: EF Core LINQ Queries
FAQ
When hard delete?
GDPR erasure or truly ephemeral data — otherwise prefer soft delete for e-commerce.