Marten: Soft Deletes

Created on 28 Apr 2016  路  7Comments  路  Source: JasperFx/marten

If a document type is so marked, treat deletions of that document as a "soft delete." Maybe have:

var store = DocumentStore(_ => {
    _.For<User>().SoftDeletes();


});

That would force Marten to add an additional column to the storage table for "deleted" and make that false by default. We would then need to intercept deletion requests and do it instead by marking the "deleted" column to true.

The DocumentMapping default query filtering would then need to set deleted = false so that normal calls to session.Query<User>() would automatically filter out soft deleted documents.

Come back with an explicit "session.Query().IncludeDeleted()" that would get you out of the deletions.

Most helpful comment

Bad phrasing on my part. So how about:

IncludeDeleted() gets you all documents regardless of deletion status, and OnlyDeleted() does exactly what it sounds like?

All 7 comments

Come back with an explicit "session.Query().IncludeDeleted()" that would get you out of the deletions.

The .IncludeDelete() implies that this will return documents that have and _have not_ been soft deleted, right? So then would there also be a: session.Query().OnlyDeleted()?

Bad phrasing on my part. So how about:

IncludeDeleted() gets you all documents regardless of deletion status, and OnlyDeleted() does exactly what it sounds like?

Would it be beneficial to have the deleted column be a DateTime so you can see when it was deleted?
For example, deleted_at would be null if not deleted yet, or it would have the time it was deleted at if deleted.

@headdetect Hadn't thought about that, but yeah, we'll do that.

Tasking for this -- but this is only a preliminary guess jotted down just to give @nieve a head start if he still wants to do it;)

  • [x] DocumentMapping.DeletionStyle = Remove/SoftDelete
  • [x] `StoreOptions.Schema.For().SoftDeletes()
  • [x] [SoftDelete] attribute as an alternative
  • [x] If soft deleted, DocumentMapping needs to add a "deleted" field
  • [x] DocumentMapping.FilterDocuments() will need to add something for "deleted = false"
  • [x] IQueryableDocument.FilterDocuments() probably needs to take in the QueryModel so it could search
    for result operators to "know" how to create the filter
  • [x] Linq support for IncludeDeleted(), including the compiled query
  • [x] Linq support for DeletedOnly(), including the compiled query
  • [x] Test that the patch generation for adding the soft delete option to an existing table
  • [x] Have to change the UpdateBatch mechanics for deletions. One way or another, the deletion has to be done by bouncing through IDocumentStorage for the document type to "know" how to add the right ICall for deletion

Great stuff, will get cracking :smile:
One thing though- the "deleted" field, shouldn't it be deleted_at (nullable DateTime, null by default) as mentioned above?

@nieve I was thinking two fields, but yeah, deleted_at as a nullable field is probably easier. Another thing I've kicked around on paper is creating a new concept of an IDeleter<T> that only governs creating the SQL for doing both the delete by Id and delete by where clause. I'm seeing 4 permutations of it:

  1. Normal removals
  2. Soft deletes
  3. Subclass normal removals
  4. Hierarchical soft deletes

Maybe we could build out those four flavors of IDeleter, and have it determined just once per doc type and used throughout?

Was this page helpful?
0 / 5 - 0 ratings