Reputation: 3068
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
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
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
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