Home > Mobile >  What is the right way to soft delete a set of rows using ef core?
What is the right way to soft delete a set of rows using ef core?

Time:09-21

I have a database which contains a table about some Users.

Schema looks like this :

 User : (id, name, username, email, phone, when_deleted)

I use ef core to interact with this table from an asp.net core app. The entity class is as follows.

 public class User
    {
        public int id { get; set; }
        public string name { get; set; }
        public string username { get; set; }
        public string email { get; set; }
        public string phone { get; set; }
    }

I have ASP.NET core background service that sends a GET request to a vendor REST API endpoint to bring latest info about the users.

[
{
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "[email protected]",
      "phone": "1-770-736-8031 x56442"
  },
{
    "id": 2,
    "name": "Jhon Doe",
    "username": "JDoe",
    "email": "[email protected]",
      "phone": "1-404-536-8031 x56442"
  }
]

Users can be deleted on the API side, but on my side I don't want to delete them, I want just to soft delete or mark them as deleted using a flag, something like when_deleted.

How can I do this the right way?

CodePudding user response:

One way to do it is through Global Filter Queries.

Global query filters are LINQ query predicates applied to Entity Types in the metadata model (usually in OnModelCreating). A query predicate is a boolean expression typically passed to the LINQ Where query operator. EF Core applies such filters automatically to any LINQ queries involving those Entity Types. EF Core also applies them to Entity Types, referenced indirectly through use of Include or navigation property. Some common applications of this feature are:

Soft delete - An Entity Type defines an IsDeleted property.

You would add the when_deleted property to the User entity. Note that I'm using a DateTime? here because the name of the property leads me to believe it is a DateTime. It should be easy enough to modify this to make it a bool instead if that is what you want.

public class User
{
    public int id { get; set; }
    public string name { get; set; }
    public string username { get; set; }
    public string email { get; set; }
    public string phone { get; set; }
    // The when_deleted property needs to be a nullable DateTime since an
    // entity that is not deleted will not have a when_deleted value.
    public DateTime? when_deleted { get; set; }
}

Then when you're configuring the entity type (usually in OnModelCreating on the DbContext) you would specify the filter query.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>().HasQueryFilter(u => u.when_deleted == null);
}

Now whenever you query the User entity, only those entities whose when_deleted property is null will be returned.

When you detect that a User has been deleted, instead of removing them from the DbSet just set the when_deleted property to DateTime.UtcNow or DateTime.Now, whichever is appropriate for your situation.

  • Related