Browse Source

Merge pull request #19531 from abpframework/auto-merge/rel-8-1/2630

Merge branch dev with rel-8.1
pull/19534/head
maliming 2 years ago
committed by GitHub
parent
commit
5a0decea4e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  2. 2
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs
  3. 84
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs
  4. 15
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs
  5. 15
      npm/ng-packs/packages/core/src/lib/services/router-events.service.ts

6
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -358,6 +358,12 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext,
ApplyAbpConceptsForModifiedEntity(entry);
if (entry.Properties.Any(x => x.IsModified && (x.Metadata.ValueGenerated == ValueGenerated.Never || x.Metadata.ValueGenerated == ValueGenerated.OnAdd)))
{
if (entry.Properties.Where(x => x.IsModified).All(x => x.Metadata.IsForeignKey()))
{
// Skip `PublishEntityDeletedEvent/PublishEntityUpdatedEvent` if only foreign keys have changed.
break;
}
if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted)
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity);

2
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs

@ -50,7 +50,7 @@ public class AbpEfCoreNavigationHelper : ITransientDependency
var index = 0;
foreach (var navigationEntry in entityEntry.Navigations.Where(navigation => !navigation.IsModified))
{
if (!navigationEntry.IsLoaded)
if (!navigationEntry.IsLoaded && navigationEntry.CurrentValue == null)
{
index++;
continue;

84
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs

@ -1,4 +1,16 @@
using Volo.Abp.TestApp.Testing;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.EntityFrameworkCore.DependencyInjection;
using Volo.Abp.EventBus.Local;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.TestApp.Testing;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.EntityFrameworkCore.DomainEvents;
@ -9,3 +21,73 @@ public class DomainEvents_Tests : DomainEvents_Tests<AbpEntityFrameworkCoreTestM
public class AbpEntityChangeOptions_DomainEvents_Tests : AbpEntityChangeOptions_DomainEvents_Tests<AbpEntityFrameworkCoreTestModule>
{
}
public class AbpEfCoreDomainEvents_Tests : EntityFrameworkCoreTestBase
{
protected readonly IRepository<AppEntityWithNavigations, Guid> AppEntityWithNavigationsRepository;
protected readonly ILocalEventBus LocalEventBus;
public AbpEfCoreDomainEvents_Tests()
{
AppEntityWithNavigationsRepository = GetRequiredService<IRepository<AppEntityWithNavigations, Guid>>();
LocalEventBus = GetRequiredService<ILocalEventBus>();
}
protected override void AfterAddApplication(IServiceCollection services)
{
services.Configure<AbpEntityOptions>(options =>
{
options.Entity<AppEntityWithNavigations>(opt =>
{
opt.DefaultWithDetailsFunc = q => q;
});
});
base.AfterAddApplication(services);
}
[Fact]
public async Task Should_Trigger_Domain_Events_For_Aggregate_Root_When_EnsureCollectionLoaded_Navigation_Changes_Tests()
{
var entityId = Guid.NewGuid();
await AppEntityWithNavigationsRepository.InsertAsync(new AppEntityWithNavigations(entityId, "TestEntity")
{
OneToMany = new List<AppEntityWithNavigationChildOneToMany>()
{
new AppEntityWithNavigationChildOneToMany
{
ChildName = "ChildName1"
}
}
});
var entityUpdatedEventTriggered = false;
LocalEventBus.Subscribe<EntityUpdatedEventData<AppEntityWithNavigations>>(data =>
{
entityUpdatedEventTriggered = !entityUpdatedEventTriggered;
return Task.CompletedTask;
});
using (var scope = ServiceProvider.CreateScope())
{
var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
using (var uow = uowManager.Begin())
{
var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId);
entity.OneToMany.ShouldBeNull();
await AppEntityWithNavigationsRepository.EnsureCollectionLoadedAsync(entity, x => x.OneToMany);
entity.OneToMany.ShouldNotBeNull();
entity.OneToMany.Clear();
await AppEntityWithNavigationsRepository.UpdateAsync(entity);
await uow.CompleteAsync();
}
}
entityUpdatedEventTriggered.ShouldBeTrue();
}
}

15
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs

@ -200,6 +200,11 @@ public abstract class DomainEvents_Tests<TStartupModule> : TestAppTestBase<TStar
});
entityUpdatedEventTriggered.ShouldBeTrue();
LocalEventBus.Subscribe<EntityUpdatedEventData<AppEntityWithValueObjectAddress>>(data =>
{
throw new Exception("Should not trigger this event");
});
// Test with value object
entityUpdatedEventTriggered = false;
await WithUnitOfWorkAsync(async () =>
@ -232,6 +237,11 @@ public abstract class DomainEvents_Tests<TStartupModule> : TestAppTestBase<TStar
});
entityUpdatedEventTriggered.ShouldBeTrue();
LocalEventBus.Subscribe<EntityUpdatedEventData<AppEntityWithNavigationChildOneToOne>>(data =>
{
throw new Exception("Should not trigger this event");
});
entityUpdatedEventTriggered = false;
await WithUnitOfWorkAsync(async () =>
{
@ -258,6 +268,11 @@ public abstract class DomainEvents_Tests<TStartupModule> : TestAppTestBase<TStar
});
entityUpdatedEventTriggered.ShouldBeTrue();
LocalEventBus.Subscribe<EntityUpdatedEventData<AppEntityWithNavigationChildOneToMany>>(data =>
{
throw new Exception("Should not trigger this event");
});
entityUpdatedEventTriggered = false;
await WithUnitOfWorkAsync(async () =>
{

15
npm/ng-packs/packages/core/src/lib/services/router-events.service.ts

@ -34,15 +34,12 @@ export class RouterEvents {
}
protected listenToNavigation(): void {
(
this.router.events.pipe(
filter(e => e instanceof NavigationEvent.End && !e.url.includes('error')),
) as Observable<NavigationEnd>
).subscribe(event => {
// It must be "NavigationTransition" but it is not exported in Angular
//https://github.com/angular/angular/blob/9c486c96827a9282cbdbff176761bc95554a260b/packages/router/src/navigation_transition.ts#L282
this.#previousNavigation.set(this.#currentNavigation());
const routerEvent$ = this.router.events.pipe(
filter(e => e instanceof NavigationEvent.End && !e.url.includes('error'))
) as Observable<NavigationEnd>;
routerEvent$.subscribe(event => {
this.#previousNavigation.set(this.currentNavigation());
this.#currentNavigation.set(event.url);
});
}

Loading…
Cancel
Save