Add a nullable DeletedAt (and optionally DeletedBy) and use an EF Core global query filter. Soft deletion should be an explicit domain operation, not an accidental update. Example: modelBuilder.Entity<Product>().HasQueryFilter(x => x.DeletedAt == null && x.RestaurantId == tenant.RestaurantId && x.OutletId == tenant.OutletId); product.DeletedAt = clock.UtcNow; Administrative restore queries may use IgnoreQueryFilters(), but must immediately reapply RestaurantId and OutletId from the authenticated context. Decide how unique indexes treat deleted rows, cascade or restrict dependent records deliberately, and retain hard-delete/retention procedures for privacy and storage requirements.
Backbencher Developer · · 0 likes