Browse Source
Merge pull request #24473 from abpframework/auto-merge/rel-10-0/4217
Merge branch dev with rel-10.0
pull/24475/head
Ma Liming
1 month ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with
47 additions and
2 deletions
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseCollection.cs
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/SoftDelete_Tests.cs
@ -686,6 +686,12 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext,
return ;
}
string? concurrencyStamp = null ;
if ( entry . Entity is IHasConcurrencyStamp hasConcurrencyStamp )
{
concurrencyStamp = hasConcurrencyStamp . ConcurrencyStamp ;
}
ExtraPropertyDictionary ? originalExtraProperties = null ;
if ( entry . Entity is IHasExtraProperties )
{
@ -694,6 +700,11 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext,
entry . Reload ( ) ;
if ( concurrencyStamp ! = null & & entry . Entity is IHasConcurrencyStamp )
{
ObjectHelper . TrySetProperty ( entry . Entity . As < IHasConcurrencyStamp > ( ) , x = > x . ConcurrencyStamp , ( ) = > concurrencyStamp ) ;
}
if ( entry . Entity is IHasExtraProperties )
{
ObjectHelper . TrySetProperty ( entry . Entity . As < IHasExtraProperties > ( ) , x = > x . ExtraProperties , ( ) = > originalExtraProperties ) ;
@ -1,6 +1,7 @@
using System ;
using System.Collections ;
using System.Collections.Generic ;
using Volo.Abp.Data ;
using Volo.Abp.Domain.Entities ;
namespace Volo.Abp.Domain.Repositories.MemoryDb ;
@ -37,10 +38,21 @@ public class MemoryDatabaseCollection<TEntity> : IMemoryDatabaseCollection<TEnti
public void Update ( TEntity entity )
{
if ( _d ictionary . ContainsKey ( GetEntityKey ( entity ) ) )
if ( ! _d ictionary . ContainsKey ( GetEntityKey ( entity ) ) )
{
_d ictionary [ GetEntityKey ( entity ) ] = _ memoryDbSerializer . Serialize ( entity ) ;
return ;
}
var originalEntity = _ memoryDbSerializer . Deserialize ( _d ictionary [ GetEntityKey ( entity ) ] , typeof ( TEntity ) ) . As < TEntity > ( ) ;
if ( entity is IHasConcurrencyStamp hasConcurrencyStamp & & originalEntity is IHasConcurrencyStamp originalHasConcurrencyStamp )
{
if ( hasConcurrencyStamp . ConcurrencyStamp ! = originalHasConcurrencyStamp . ConcurrencyStamp )
{
throw new AbpDbConcurrencyException ( "Database operation expected to affect 1 row but actually affected 0 row. Data may have been modified or deleted since entities were loaded. This exception has been thrown on optimistic concurrency check." ) ;
}
}
_d ictionary [ GetEntityKey ( entity ) ] = _ memoryDbSerializer . Serialize ( entity ) ;
}
public void Remove ( TEntity entity )
@ -139,4 +139,26 @@ public abstract class SoftDelete_Tests<TStartupModule> : TestAppTestBase<TStartu
douglas . Phones . ShouldNotBeEmpty ( ) ;
}
}
[Fact]
public async Task Soft_Delete_Should_Check_Concurrency ( )
{
var douglas = await PersonRepository . GetAsync ( TestDataBuilder . UserDouglasId ) ;
douglas . ConcurrencyStamp . ShouldNotBeNull ( ) ;
douglas . ConcurrencyStamp = Guid . NewGuid ( ) . ToString ( ) ;
await Assert . ThrowsAsync < AbpDbConcurrencyException > ( async ( ) = >
{
await PersonRepository . DeleteAsync ( douglas ) ;
} ) ;
douglas = await PersonRepository . GetAsync ( TestDataBuilder . UserDouglasId ) ;
douglas . ConcurrencyStamp . ShouldNotBeNull ( ) ;
// Modify the entity to verify that a changed entity with a correct ConcurrencyStamp
// can still be soft deleted without raising a concurrency exception.
douglas . ChangeName ( "Changed Name" ) ;
// Try again with the correct ConcurrencyStamp - this will not throw an exception
await PersonRepository . DeleteAsync ( douglas ) ;
}
}