Skip to content

Commit 5b02381

Browse files
committed
VCST-3962: Delete orphaned entities (#466)
1 parent 1df45be commit 5b02381

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/VirtoCommerce.OrdersModule.Data/Repositories/OrderRepository.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Threading.Tasks;
55
using Microsoft.EntityFrameworkCore;
6+
using Microsoft.EntityFrameworkCore.ChangeTracking;
67
using VirtoCommerce.OrdersModule.Core.Model;
78
using VirtoCommerce.OrdersModule.Data.Model;
89
using VirtoCommerce.Platform.Core.Common;
@@ -17,6 +18,9 @@ public class OrderRepository : DbContextRepositoryBase<OrderDbContext>, IOrderRe
1718
public OrderRepository(OrderDbContext dbContext, IUnitOfWork unitOfWork = null)
1819
: base(dbContext, unitOfWork)
1920
{
21+
// Resolves Breaking changes in EF Core 7.0 (EF7) when EF Core will not automatically delete orphans because all FKs are nullable.
22+
// https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/breaking-changes?tabs=v7#orphaned-dependents-of-optional-relationships-are-not-automatically-deleted
23+
dbContext.SavingChanges += OnSavingChanges;
2024
}
2125

2226
public IQueryable<CustomerOrderEntity> CustomerOrders => DbContext.Set<CustomerOrderEntity>();
@@ -261,5 +265,72 @@ public virtual async Task RemoveOrdersByIdsAsync(IList<string> ids)
261265
}
262266
}
263267
#pragma warning restore S109
268+
269+
protected override void Dispose(bool disposing)
270+
{
271+
if (disposing && DbContext != null)
272+
{
273+
DbContext.SavingChanges -= OnSavingChanges;
274+
}
275+
base.Dispose(disposing);
276+
}
277+
278+
protected virtual bool IsOrphanedEntity(EntityEntry entry)
279+
{
280+
switch (entry.Entity)
281+
{
282+
case CaptureEntity capture
283+
when capture.PaymentId == null:
284+
case RefundEntity refund
285+
when refund.PaymentId == null:
286+
case PaymentInEntity payment
287+
when payment.CustomerOrderId == null
288+
&& payment.ShipmentId == null:
289+
case AddressEntity a
290+
when a.CustomerOrderId == null
291+
&& a.ShipmentId == null
292+
&& a.PaymentInId == null:
293+
case DiscountEntity d
294+
when d.CustomerOrderId == null
295+
&& d.ShipmentId == null
296+
&& d.LineItemId == null
297+
&& d.PaymentInId == null:
298+
case TaxDetailEntity t
299+
when t.CustomerOrderId == null
300+
&& t.ShipmentId == null
301+
&& t.LineItemId == null
302+
&& t.PaymentInId == null:
303+
case FeeDetailEntity f
304+
when f.CustomerOrderId == null
305+
&& f.ShipmentId == null
306+
&& f.LineItemId == null
307+
&& f.PaymentInId == null:
308+
case OrderDynamicPropertyObjectValueEntity v
309+
when v.CustomerOrderId == null
310+
&& v.PaymentInId == null
311+
&& v.ShipmentId == null
312+
&& v.RefundId == null
313+
&& v.LineItemId == null
314+
&& v.CaptureId == null:
315+
return true;
316+
}
317+
318+
return false;
319+
}
320+
321+
private void OnSavingChanges(object sender, SavingChangesEventArgs args)
322+
{
323+
var ctx = (DbContext)sender;
324+
var entries = ctx.ChangeTracker.Entries();
325+
326+
foreach (var entry in entries)
327+
{
328+
if (entry.State == EntityState.Modified &&
329+
IsOrphanedEntity(entry))
330+
{
331+
entry.State = EntityState.Deleted;
332+
}
333+
}
334+
}
264335
}
265336
}

0 commit comments

Comments
 (0)