diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs index 4b8a531db1..8d597f85b5 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs @@ -21,10 +21,7 @@ public class AbpEntityEntry { return _isModified || EntityEntry.State == EntityState.Modified || NavigationEntries.Any(n => n.IsModified); } - set - { - _isModified = value; - } + set => _isModified = value; } public AbpEntityEntry(string id, EntityEntry entityEntry) @@ -46,14 +43,11 @@ public class AbpEntityEntry continue; } - var navigation = EntityEntry.Navigations.FirstOrDefault(n => n.Metadata.Name == navigationEntry.Name); - - var currentValue = AbpNavigationEntry.GetOriginalValue(navigation?.CurrentValue); + var currentValue = AbpNavigationEntry.GetOriginalValue(navigationEntry.NavigationEntry.CurrentValue); if (currentValue == null) { continue; } - switch (navigationEntry.OriginalValue) { case null: diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs index 4533a66d72..c1ff65b76b 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs @@ -1,7 +1,7 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Domain.Repositories; @@ -13,12 +13,10 @@ namespace Volo.Abp.EntityFrameworkCore; public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase { private readonly IRepository _blogRepository; - private readonly IRepository _postRepository; public AbpEfCoreNavigationHelper_Tests() { _blogRepository = GetRequiredService>(); - _postRepository = GetRequiredService>(); } [Fact] @@ -30,8 +28,12 @@ public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase return; } - var stopWatch = Stopwatch.StartNew(); + //These time taken varies on different machines. + //I used relatively large values, but it can also check for performance problem. + var batchUpdateTime = TimeSpan.FromSeconds(30); + var queryTime = TimeSpan.FromSeconds(10); + var stopWatch = Stopwatch.StartNew(); await WithUnitOfWorkAsync(async () => { for (var i = 0; i < 5 * 1000; i++) @@ -40,32 +42,54 @@ public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase new Blog(Guid.NewGuid()) { Name = "Blog" + i, - BlogPosts = new List - { - new BlogPost + BlogPosts = + [ + new BlogPost(Guid.NewGuid()) { - Post = new Post(Guid.NewGuid()) - { - Title = "Post" + i - } + Title = "Post" + i } - } + ] }); } }); - stopWatch.Stop(); - stopWatch.Elapsed.ShouldBeLessThan(TimeSpan.FromSeconds(10)); + stopWatch.Elapsed.ShouldBeLessThan(batchUpdateTime); + stopWatch.Restart(); var blogs = await _blogRepository.GetListAsync(includeDetails: true); - var posts = await _postRepository.GetListAsync(includeDetails: true); blogs.Count.ShouldBe(5 * 1000); - blogs.SelectMany(x => x.BlogPosts.Select(y => y.Post)).Count().ShouldBe(5 * 1000); - posts.Count.ShouldBe(5 * 1000); - posts.SelectMany(x => x.BlogPosts.Select(y => y.Blog)).Count().ShouldBe(5 * 1000); + blogs.SelectMany(x => x.BlogPosts).Count().ShouldBe(5 * 1000); + stopWatch.Stop(); + stopWatch.Elapsed.ShouldBeLessThan(queryTime); + + var blogId = blogs.First().Id; + stopWatch.Restart(); + await WithUnitOfWorkAsync(async () => + { + var blog = await _blogRepository.GetAsync(blogId); + blog.ShouldNotBeNull(); + for (var i = 0; i < 5 * 1000; i++) + { + blog.BlogPosts.Add( + new BlogPost(Guid.NewGuid()) + { + Title = "NewPost" + i + }); + } + await _blogRepository.UpdateAsync(blog); + }); + stopWatch.Stop(); + stopWatch.Elapsed.ShouldBeLessThan(batchUpdateTime); + + + var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.CancelAfter(batchUpdateTime); + stopWatch.Restart(); + var blog = await _blogRepository.GetAsync(blogId, cancellationToken: cancellationTokenSource.Token); + blog.BlogPosts.Count.ShouldBe(5 * 1000 + 1); stopWatch.Stop(); - stopWatch.Elapsed.ShouldBeLessThan(TimeSpan.FromSeconds(1)); + stopWatch.Elapsed.ShouldBeLessThan(queryTime); } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs index 691383643d..22c0b92477 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -56,11 +56,7 @@ public class AbpEntityFrameworkCoreTestModule : AbpModule options.Entity(opt => { - opt.DefaultWithDetailsFunc = q => q.Include(p => p.BlogPosts).ThenInclude(bp => bp.Post); - }); - options.Entity(opt => - { - opt.DefaultWithDetailsFunc = q => q.Include(p => p.BlogPosts).ThenInclude(bp => bp.Blog); + opt.DefaultWithDetailsFunc = q => q.Include(p => p.BlogPosts); }); }); diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs index aac69f3935..d05e367ff7 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs @@ -31,7 +31,6 @@ public class TestMigrationsDbContext : AbpDbContext public DbSet AppEntityWithNavigationsForeign { get; set; } public DbSet Blogs { get; set; } - public DbSet Posts { get; set; } public DbSet BlogPosts { get; set; } public TestMigrationsDbContext(DbContextOptions options) @@ -110,18 +109,9 @@ public class TestMigrationsDbContext : AbpDbContext .HasForeignKey(bp => bp.BlogId); }); - modelBuilder.Entity(b => - { - b.ConfigureByConvention(); - b.HasMany(bp => bp.BlogPosts) - .WithOne(bp => bp.Post) - .HasForeignKey(bp => bp.PostId); - }); - modelBuilder.Entity(b => { b.ConfigureByConvention(); - b.HasKey(p => new { p.BlogId, p.PostId }); }); } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs index e08f7f0c64..9ef826176b 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs @@ -17,28 +17,15 @@ public class Blog : FullAuditedAggregateRoot public List BlogPosts { get; set; } } -public class Post : FullAuditedAggregateRoot +public class BlogPost : Entity { - public Post(Guid id) + public BlogPost(Guid id) : base(id) { } - public string Title { get; set; } - - public List BlogPosts { get; set; } -} - -public class BlogPost : Entity -{ public Guid BlogId { get; set; } public Blog Blog { get; set; } - public Guid PostId { get; set; } - public Post Post { get; set; } - - public override object[] GetKeys() - { - return new object[] { BlogId, PostId }; - } + public string Title { get; set; } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs index 8791dde46b..242809bf7c 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs @@ -38,7 +38,6 @@ public class TestAppDbContext : AbpDbContext, IThirdDbContext, public DbSet AppEntityWithNavigationsForeign { get; set; } public DbSet Blogs { get; set; } - public DbSet Posts { get; set; } public DbSet BlogPosts { get; set; } public TestAppDbContext(DbContextOptions options) @@ -136,18 +135,9 @@ public class TestAppDbContext : AbpDbContext, IThirdDbContext, .HasForeignKey(bp => bp.BlogId); }); - modelBuilder.Entity(b => - { - b.ConfigureByConvention(); - b.HasMany(bp => bp.BlogPosts) - .WithOne(bp => bp.Post) - .HasForeignKey(bp => bp.PostId); - }); - modelBuilder.Entity(b => { b.ConfigureByConvention(); - b.HasKey(p => new { p.BlogId, p.PostId }); }); modelBuilder.TryConfigureObjectExtensions();