Browse Source

Merge pull request #23340 from abpframework/auto-merge/rel-9-2/3881

Merge branch rel-9.3 with rel-9.2
pull/23341/head
maliming 1 year ago
committed by GitHub
parent
commit
61e380770d
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 24
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs
  2. 72
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs
  3. 6
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs

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

@ -60,7 +60,7 @@ public class AbpEfCoreNavigationHelper : ITransientDependency
return; return;
} }
var foreignKeys = entityEntry.Metadata.GetForeignKeys().ToList(); var foreignKeys = entityEntry.Metadata.GetForeignKeys();
foreach (var foreignKey in foreignKeys) foreach (var foreignKey in foreignKeys)
{ {
var principal = stateManager.FindPrincipal(internalEntityEntityEntry, foreignKey); var principal = stateManager.FindPrincipal(internalEntityEntityEntry, foreignKey);
@ -75,15 +75,20 @@ public class AbpEfCoreNavigationHelper : ITransientDependency
continue; continue;
} }
abpEntityEntry.UpdateNavigationEntries(); var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == foreignKey) ??
abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == foreignKey);
if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
{
abpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
}
if (!abpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry))) if (!abpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{ {
abpEntityEntry.IsModified = true; abpEntityEntry.IsModified = true;
DetectChanges(abpEntityEntry.EntityEntry, false); DetectChanges(abpEntityEntry.EntityEntry, false);
} }
var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == foreignKey) ??
abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == foreignKey);
if (navigationEntry != null && IsEntityEntryChanged(entityEntry)) if (navigationEntry != null && IsEntityEntryChanged(entityEntry))
{ {
navigationEntry.IsModified = true; navigationEntry.IsModified = true;
@ -115,15 +120,20 @@ public class AbpEfCoreNavigationHelper : ITransientDependency
continue; continue;
} }
abpEntityEntry.UpdateNavigationEntries(); var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == inverseForeignKey) ??
abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == inverseForeignKey);
if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
{
abpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
}
if (!abpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry))) if (!abpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{ {
abpEntityEntry.IsModified = true; abpEntityEntry.IsModified = true;
DetectChanges(abpEntityEntry.EntityEntry, false); DetectChanges(abpEntityEntry.EntityEntry, false);
} }
var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == inverseForeignKey) ??
abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == inverseForeignKey);
if (navigationEntry != null && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry))) if (navigationEntry != null && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{ {
navigationEntry.IsModified = true; navigationEntry.IsModified = true;

72
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs

@ -1,4 +1,4 @@
using System.Collections; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -31,43 +31,29 @@ public class AbpEntityEntry
NavigationEntries = EntityEntry.Navigations.Select(x => new AbpNavigationEntry(x, x.Metadata.Name)).ToList(); NavigationEntries = EntityEntry.Navigations.Select(x => new AbpNavigationEntry(x, x.Metadata.Name)).ToList();
} }
public void UpdateNavigationEntries() public void UpdateNavigation(EntityEntry entityEntry, AbpNavigationEntry navigationEntry)
{ {
foreach (var navigationEntry in NavigationEntries) if (IsModified ||
EntityEntry.State == EntityState.Modified ||
navigationEntry.IsModified)
{ {
if (IsModified || return;
EntityEntry.State == EntityState.Modified || }
navigationEntry.IsModified ||
navigationEntry.NavigationEntry.IsModified)
{
continue;
}
var currentValue = AbpNavigationEntry.GetOriginalValue(navigationEntry.NavigationEntry.CurrentValue); var currentValue = navigationEntry.NavigationEntry.CurrentValue;
if (currentValue == null) if (currentValue == null)
{ {
continue; return;
} }
switch (navigationEntry.OriginalValue)
{
case null:
navigationEntry.OriginalValue = currentValue;
break;
case IEnumerable originalValueCollection when currentValue is IEnumerable currentValueCollection:
{
var existingList = originalValueCollection.Cast<object?>().ToList();
var newList = currentValueCollection.Cast<object?>().ToList();
if (newList.Count > existingList.Count)
{
navigationEntry.OriginalValue = currentValue;
}
break; if (navigationEntry.NavigationEntry is CollectionEntry)
} {
default: navigationEntry.OriginalValue ??= new List<object>();
navigationEntry.OriginalValue = currentValue; navigationEntry.OriginalValue.As<List<object>>().Add(entityEntry.Entity);
break; }
} else
{
navigationEntry.OriginalValue = currentValue;
} }
} }
} }
@ -80,7 +66,7 @@ public class AbpNavigationEntry
public bool IsModified { get; set; } public bool IsModified { get; set; }
public List<object>? OriginalValue { get; set; } public object? OriginalValue { get; set; }
public object? CurrentValue => NavigationEntry.CurrentValue; public object? CurrentValue => NavigationEntry.CurrentValue;
@ -88,21 +74,9 @@ public class AbpNavigationEntry
{ {
NavigationEntry = navigationEntry; NavigationEntry = navigationEntry;
Name = name; Name = name;
OriginalValue = GetOriginalValue(navigationEntry.CurrentValue); if (navigationEntry.CurrentValue != null )
}
public static List<object>? GetOriginalValue(object? currentValue)
{
if (currentValue is null)
{
return null;
}
if (currentValue is IEnumerable enumerable)
{ {
return enumerable.Cast<object>().ToList(); OriginalValue = navigationEntry is CollectionEntry ? new List<object>() : navigationEntry.CurrentValue;
} }
return new List<object> { currentValue };
} }
} }

6
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs

@ -1,7 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Shouldly; using Shouldly;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
@ -84,11 +83,8 @@ public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase
stopWatch.Stop(); stopWatch.Stop();
stopWatch.Elapsed.ShouldBeLessThan(batchUpdateTime); stopWatch.Elapsed.ShouldBeLessThan(batchUpdateTime);
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.CancelAfter(batchUpdateTime);
stopWatch.Restart(); stopWatch.Restart();
var blog = await _blogRepository.GetAsync(blogId, cancellationToken: cancellationTokenSource.Token); var blog = await _blogRepository.GetAsync(blogId);
blog.BlogPosts.Count.ShouldBe(5 * 1000 + 1); blog.BlogPosts.Count.ShouldBe(5 * 1000 + 1);
stopWatch.Stop(); stopWatch.Stop();
stopWatch.Elapsed.ShouldBeLessThan(queryTime); stopWatch.Elapsed.ShouldBeLessThan(queryTime);

Loading…
Cancel
Save