Aleksej_Shherbak
Aleksej_Shherbak

Reputation: 3068

Is there something like OnDelete callback for ASP.NET Core model?

I have the following model:

 public class MyFiles
    {
        public int MyFilesId { get; set; }
        public string Name { get; set; }
        public string Path { get; set; }
    }

As you can understand it's a model for uploaded files. Each model keeps path to wwwroot/ ... and file's (image for example) name. But how to delete a file when I delete this model? I mean:

var res = _applicationDbContext.MyFiles.FirstOrDefault(x => x.MyFilesId = 666);
_applicationDbContext.MyFiles.Remove(res);
_applicationDbContext.SaveChanges();

Of course, the above code will not delete file. It would very useful if I can write something like:

 public class MyFiles
    {
        public int MyFilesId { get; set; }
        public string Name { get; set; }
        public string Path { get; set; }

        protected OnDelete() { // here is logic for removing the file from OS }
    }

Upvotes: 2

Views: 645

Answers (3)

Fermin
Fermin

Reputation: 36081

There is no direct callback but you can override OnSave() in your DbContext and call the delete method there there.

public class MyFiles
{
  public int MyFilesId { get; set; }
  public string Name { get; set; }
  public string Path { get; set; }

  protected OnDelete() { // here is logic for removing the file from OS }
}

public class MyDbContext : DbContext
{
  public override int SaveChanges()
  {
    // iterate through deletions
    foreach (var item in ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted))
    {
      // if item being deleted is MyFiles, call OnDelete
      if (item.Entity is MyFiles myFile)
        myFile.OnDelete();
    }

    return base.SaveChanges();
  }
}

I'm unaware of how long it will take to delete the file from the OS, how often this will happen and how important it is to delete the file immediately. However, if it takes time to delete a file adding this logic could considerably slow down your context.SaveChanges() calls. To avoid this I would consider adding 'files to be deleted' to some sort of queue so that these can be processed independantly of the save operation on the dbcontext.

Upvotes: 2

Athanasios Kataras
Athanasios Kataras

Reputation: 26362

There is no event mechanism to subscribe to in EF. What you could do though would be to override the SaveChanges as described here

What is described is a variation of the following:

public interface IFileSystemEntity
{
      string Path { get; set; }
}

public class MyFiles: IFileSystemEntity
{
    public int MyFilesId { get; set; }
    public string Name { get; set; }
    public string Path { get; set; }

    protected OnDelete() { // here is logic for removing the file from OS }
}

And then in your DBContext

public override int SaveChanges()
{
    this.ChangeTracker.DetectChanges();
    var added = this.ChangeTracker.Entries()
                .Where(t => t.State == EntityState.Deleted)
                .Select(t => t.Entity)
                .ToArray();

    foreach (var entity in added)
    {
        if (entity is IFileSystemEntity)
        {
            var track = entity as IFileSystemEntity;
            // Remove logic here
        }
    }
    return base.SaveChanges();
}

Upvotes: 2

kalit
kalit

Reputation: 266

You can override method SaveChanges() and call in it to check deleted object in ChangeTracker and call your callback

public override int SaveChanges(bool acceptAllChangesOnSuccess)
    {
        foreach (var entityEntry in ChangeTracker.Entries().Where(entry => entry.State == EntityState.Deleted))
        {
            var oldEntity = entityEntry.Entity;
            // my callback
        }

        return base.SaveChanges(acceptAllChangesOnSuccess);
    }

Upvotes: 1

Related Questions