Hi,
Consider the following code.
var proposal = await _travelOfferPriceProposalRepository.GetAll()
.Include(b => b.TravelOfferPriceProposalElements).ThenInclude(b => b.TravelElement)
.Include(b => b.TravelOfferPriceProposalGroups).ThenInclude(b => b.TravelOfferPriceProposalElements).ThenInclude(b => b.TravelElement)
.FirstOrDefaultAsync(b => b.Id == id);
///
// This code will automatically do hard delete the data we have. Without any notification.
// Due to UnitOfWork.
///
proposal.TravelOfferPriceProposalElements = proposal.TravelOfferPriceProposalElements
.Where(b => b.TravelOfferPriceProposalGroupId == null && b.TravelOfferPriceProposalId == id).ToList();
///
///
// Need to use this instead
var test = ObjectMapper.Map<TravelOfferPriceProposalDto>(proposal);
test.TravelOfferPriceProposalElements = test.TravelOfferPriceProposalElements
.Where(b => b.TravelOfferPriceProposalGroupId == null && b.TravelOfferPriceProposalId == id).ToList();
return test;
As you can see our software team has made the logical error of filter out data and storing it on the same entity, causing it to delete the actual data from our database instead of just doing a filterd get.
We understand the issue, however the above code causes a hard delete on our records. Despite the fact that TravelOfferPriceProposalElement is a full audited entity. Should that not be a soft delete?
Is this a issue/shortcomming of the ISoftDelete interface combined with EFCore or is this normal behaviour? If this is normal how can we log hard deletes for fullauditedentities on a application level?
We believe our team has made this mistake on multiple appservices.
Thanks in advance for any advice given.
6 Answer(s)
-
0
Despite the fact that TravelOfferPriceProposalElement is a full audited entity. Should that not be a soft delete?
It should.
Is this a issue/shortcoming of the ISoftDelete interface combined with EF Core or is this normal behaviour? If this is normal how can we log hard deletes for fullauditedentities on a application level?
It's because EF Core sets
entry.State
toEntityState.Modified
and foreign key tonull
, and implicitly deletes. It's normal in EF Core, but probably not expected forISoftDelete
concept.You can override
ApplyAbpConcepts
inDbContext
with this partial fix that assumes parent entity is not hard deleted:protected override void ApplyAbpConcepts(EntityEntry entry, long? userId, EntityChangeReport changeReport) { HandleImplicitDeleteForSoftDelete(entry); base.ApplyAbpConcepts(entry, userId, changeReport); } protected virtual void HandleImplicitDeleteForSoftDelete(EntityEntry entry) { if (entry.State == EntityState.Modified && entry.Entity is ISoftDelete) { var foreignKeys = entry.Metadata.GetForeignKeys(); foreach (var foreignKey in foreignKeys) { foreach (var property in foreignKey.Properties) { var propertyEntry = entry.Property(property.Name); if (propertyEntry.OriginalValue != null && propertyEntry.CurrentValue == null) { entry.State = EntityState.Deleted; } } } } }
-
0
That totally makes sense! Thank you for your help. We will apply your solution.
-
0
I tried the above solution:
- adding the above code to my DbContext class.
- delete async as follows:
using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete)) { await _roomRepository.DeleteAsync(input.Id); /* input.Id = 6 */ }
Yet the records are still soft deleted. How can I actually remove records from a table so that, for example, record id = 6 does not exist in the table?
Hard delete is a non-negotiable requirement for my application. Absent hard delete the database size would explode in a short time, and consist of 95% soft deleted records.
-
0
The code above specifically prevents implicit hard delete.
If you don't ever want to soft delete, then don't implement an
ISoftDelete
in the first place. -
0
OK, don't use the above code. Your answer isn't very hepful. I am using the RAD tool to emit code which implements (somewhere, Apb?) soft delete.
ISoftDelete
does not exist in my app, ergo, I can't not do something that does not exist. Please show by example how to "not implementISoftDelete
" so that I can hard delete a record in a standard ANZ app. -
0
Inherit
Entity
instead ofFullAuditesEntity
.