From 6357bd6c04db5553ddd13f9821eca17eb0d74e8a Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 23 Apr 2025 16:54:48 +0800 Subject: [PATCH] Add unit test for `UpdateAggregateRootWhenNavigationChanges`. --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 5 +- .../DomainEvents/DomainEvents_Tests.cs | 105 ++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index d68616e69f..96aff4e0b0 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -446,7 +446,10 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, EntityChangeOptions.Value.IgnoredNavigationEntitySelectors.All(selector => !selector.Predicate(entry.Entity.GetType())) && AbpEfCoreNavigationHelper.IsNavigationEntryModified(entry)) { - ApplyAbpConceptsForModifiedEntity(entry, true); + if (EntityChangeOptions.Value.UpdateAggregateRootWhenNavigationChanges) + { + ApplyAbpConceptsForModifiedEntity(entry, true); + } if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted) { EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity); diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs index d82fb195ab..26be74c34d 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs @@ -45,6 +45,111 @@ public class AbpEntityChangeOptions_DomainEvents_IgnoreEntityChangeSelectorList_ } } +public class AbpEfCoreDomainEvents_UpdateAggregateRootWhenNavigationChanges_Tests : EntityFrameworkCoreTestBase +{ + protected readonly IRepository AppEntityWithNavigationsRepository; + protected readonly IRepository AppEntityWithNavigationForeignRepository; + protected readonly ILocalEventBus LocalEventBus; + + public AbpEfCoreDomainEvents_UpdateAggregateRootWhenNavigationChanges_Tests() + { + AppEntityWithNavigationsRepository = GetRequiredService>(); + AppEntityWithNavigationForeignRepository = GetRequiredService>(); + LocalEventBus = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.PublishEntityUpdatedEventWhenNavigationChanges = true; + options.UpdateAggregateRootWhenNavigationChanges = false; + }); + + base.AfterAddApplication(services); + } + + [Fact] + public async Task Should_Trigger_Domain_Events_But_Do_Not_Change_Aggregate_Root_When_Navigation_Changes_Tests() + { + var entityId = Guid.NewGuid(); + + var newEntity = await AppEntityWithNavigationsRepository.InsertAsync(new AppEntityWithNavigations(entityId, "TestEntity")); + + var latestConcurrencyStamp = newEntity.ConcurrencyStamp; + var lastModificationTime = newEntity.LastModificationTime; + + var entityUpdatedEventTriggered = false; + + LocalEventBus.Subscribe>(data => + { + entityUpdatedEventTriggered = true; + + // The Aggregate will not be updated + data.Entity.ConcurrencyStamp.ShouldBe(latestConcurrencyStamp); + data.Entity.LastModificationTime.ShouldBe(lastModificationTime); + return Task.CompletedTask; + }); + + // Test with value object + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.AppEntityWithValueObjectAddress = new AppEntityWithValueObjectAddress("Turkey"); + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + + // Test with one to one + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.OneToOne = new AppEntityWithNavigationChildOneToOne + { + ChildName = "ChildName" + }; + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + + // Test with one to many + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.OneToMany = new List() + { + new AppEntityWithNavigationChildOneToMany + { + AppEntityWithNavigationId = entity.Id, + ChildName = "ChildName1" + } + }; + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + + // Test with many to many + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.ManyToMany = new List() + { + new AppEntityWithNavigationChildManyToMany + { + ChildName = "ChildName1" + } + }; + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + } + +} + public class AbpEfCoreDomainEvents_Tests : EntityFrameworkCoreTestBase { protected readonly IRepository AppEntityWithNavigationsRepository;