I have bunch of tables that contain DeletedAt
column that's used for a soft-delete
feature. I've implemented most of the logic and everything works correctly except for one issue where it allows to add a child record to a soft-deleted parent record. I'd like to throw an exception when DbContext.OnSave()
runs and finds that the parent record (foreignKey
) is actually soft-deleted
.
Is there any way I can inject a filter or something that can check for that parent DeletedAt
field before adding the child element?
I do have few ideas but kinda painful and require to loop through all foreignKeys in the child model and checks if that parent object has DeletedAt
set or not.
Any ideas would be appreciated. Thanks.
So I did find a solution and it's not that bad, here's the implementation for anyone who's interested (before your code hits the DbContext.SaveChanges()
) in the DbContext
file:
var entry = Entry(childModel);
foreach(var prop in entry.CurrentValues.Properties)
{
// Handle FKs only
if(!prop.IsForeignKey()) continue;
var fkValue = entry.CurrentValues[prop.Name];
// Handle nullable properties and skip the checks if the value is null
if(prop.IsColumnNullable() && fkValue == null) continue;
// If value is null or 0 then break
if(fkValue == null || (int)fkValue == 0)
{
throw new Exception("Must contain a value.");
}
// Get the FK
var fk = prop.GetContainingForeignKeys().FirstOrDefault();
if(fk == null)
{
throw new Exception("FK constraint is not available.");
}
// If parent is not available or deleted
var parent = Find(fk.PrincipalEntityType.ClrType, new object[]{fkValue});
if(parent == null)
{
throw new Exception($"The entered FK value ({fkValue}) is not valid.");
}
}
Find
method actually has a global filter that checks if the DeletedAt
field is set or not. If the record doesn't exist, this will fail. This should be dynamic enough to handle all FKs in a table.