Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ index:
- rule: public/uploads/rules/do-not-allow-nulls-in-number-fields-if-it-has-the-same-meaning-as-zero/rule.mdx
- rule: public/uploads/rules/avoid-spaces-and-empty-lines-at-the-start-of-character-columns/rule.mdx
- rule: public/uploads/rules/use-identities-in-sql-server/rule.mdx
- rule: public/uploads/rules/avoid-deleting-records-by-flagging-them-as-isdeleted/rule.mdx
- rule: public/uploads/rules/retain-deleted-records-with-a-soft-delete/rule.mdx
- rule: public/uploads/rules/make-sure-you-have-valid-date-data-in-your-database/rule.mdx
- rule: public/uploads/rules/datetime-fields-must-be-converted-to-universal-time/rule.mdx
- rule: public/uploads/rules/use-temporal-tables-to-audit-data-changes/rule.mdx
Expand Down Expand Up @@ -86,4 +86,4 @@ Here are some of the typical things that all SQL Server DBAs and Database develo

View [Database Coding Standard and Guideline](http://www.nyx.net/~bwunder/dbChangeControl/standard.htm).

Want to develop your SQL Server Database with SSW? Check [SSW's Databases consulting page](https://www.ssw.com.au/consulting/database-development).
Want to develop your SQL Server Database with SSW? Check [SSW's Databases consulting page](https://www.ssw.com.au/consulting/database-development).
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
type: rule
title: Data - Do you avoid deleting records by flagging them as IsDeleted (aka Soft Delete)?
uri: avoid-deleting-records-by-flagging-them-as-isdeleted
title: Data - Do you use Soft Delete to retain deleted records?
uri: retain-deleted-records-with-a-soft-delete
categories:
- category: categories/software-engineering/rules-to-better-sql-databases-developers.mdx
authors:
Expand All @@ -10,6 +10,7 @@ authors:
redirects:
- data-do-you-avoid-deleting-records-by-flagging-them-as-isdeleted-aka-soft-delete
- data-do-you-avoid-deleting-records-by-flagging-them-as-isdeleted-(aka-soft-delete)
- do-you-know-you-can-retain-deleted-records-with-a-soft-delete
guid: 56fff82d-9ed7-4aee-ab22-68e4c61fe162
seoDescription: Avoid deleting records by flagging them as IsDeleted (aka Soft Delete) and instead keep historical data intact.
created: 2019-11-25T19:14:13.000Z
Expand Down Expand Up @@ -37,7 +38,7 @@ When users are deleting a lot of records as part of normal operations - they can
* Depending on your interface design, you may have to join to parent tables to ensure that deleted child records do not appear. Typically, the interface would be designed in such a way that you would not need be able to created new records based on the deleted items (e.g. you cannot create a new order record for a customer that is deleted). Performance of queries can potentially suffer if you have to do these joins.
* While storage space is very cheap, you are not removing records from your database. You may need to archive records if the number of deleted records becomes large.

### Best Approach for Implementing Soft Delete in EF Core for modern web application
## Best approach for implementing Soft Delete in EF Core for modern web applications

### 1. `ISoftDeleteEntity` Interface

Expand Down Expand Up @@ -67,17 +68,35 @@ Override the default delete behavior using EF Core interceptors by using an inte
```chsarp
public class SoftDeleteInterceptor : SaveChangesInterceptor
{
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
public override InterceptionResult<int> SavingChanges(
DbContextEventData eventData,
InterceptionResult<int> result)
{
foreach (var entry in eventData.Context.ChangeTracker.Entries<ISoftDeleteEntity>())
UpdateEntities(eventData.Context);
return base.SavingChanges(eventData, result);
}

public override ValueTask<InterceptionResult<int>> SavingChangesAsync(
DbContextEventData eventData,
InterceptionResult<int> result,
CancellationToken cancellationToken)
{
UpdateEntities(eventData.Context);
return base.SavingChangesAsync(eventData, result, cancellationToken);
}

private static void UpdateEntities(DbContext? context)
{
if (context is null) return;

foreach (var entry in context.ChangeTracker.Entries<ISoftDeleteEntity>())
{
if (entry.State == EntityState.Deleted)
{
entry.Entity.IsDeleted = true;
entry.State = EntityState.Modified;
entry.Entity.IsDeleted = true;
}
}
return base.SavingChanges(eventData, result);
}
}
```
Expand Down Expand Up @@ -119,16 +138,13 @@ Also see [Using Audit Tools](/use-temporal-tables-to-audit-data-changes) for a
figure=""
/>

### Soft Delete in Dynamic 365/ Dataverse (CRM)
## Soft Delete in Dynamic 365/ Dataverse (CRM)

In Dynamics 365 you rarely hard-delete. The platform already supports soft delete via record status — so deactivate instead of delete, and make any real deletion a reviewed, reversible, 2-step process.

<imageEmbed alt="Deactivate in CRM" size="medium" showBorder={false} figurePrefix="good" figure="safe deactivate-then-delete flow" src="/uploads/rules/avoid-deleting-records-by-flagging-them-as-isdeleted/soft-delete.png" />

1\. Deactivate the record

2\. Mark the affected records with an identifiable marker and run the change under a dedicated service account, so they're easy to filter, review and reverse.

3\. Present the draft list of records for sign-off before any hard delete.

4\. Run the built-in Bulk Record Deletion job with tight filters, e.g. Status Inactive AND ModifiedBy \[service account] AND ModifiedOn today.
1. Deactivate the record
2. Mark the affected records with an identifiable marker and run the change under a dedicated service account, so they're easy to filter, review and reverse
3. Present the draft list of records for sign-off before any hard delete
4. Run the built-in Bulk Record Deletion job with tight filters, e.g. Status Inactive AND ModifiedBy \[service account] AND ModifiedOn today
Loading