Browse Source

Refactor BlogPost entity and remove Post entity from tests

pull/23316/head
maliming 10 months ago
parent
commit
fafb76172f
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 10
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs
  2. 62
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs
  3. 6
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs
  4. 10
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
  5. 19
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs
  6. 10
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs

10
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); return _isModified || EntityEntry.State == EntityState.Modified || NavigationEntries.Any(n => n.IsModified);
} }
set set => _isModified = value;
{
_isModified = value;
}
} }
public AbpEntityEntry(string id, EntityEntry entityEntry) public AbpEntityEntry(string id, EntityEntry entityEntry)
@ -46,14 +43,11 @@ public class AbpEntityEntry
continue; continue;
} }
var navigation = EntityEntry.Navigations.FirstOrDefault(n => n.Metadata.Name == navigationEntry.Name); var currentValue = AbpNavigationEntry.GetOriginalValue(navigationEntry.NavigationEntry.CurrentValue);
var currentValue = AbpNavigationEntry.GetOriginalValue(navigation?.CurrentValue);
if (currentValue == null) if (currentValue == null)
{ {
continue; continue;
} }
switch (navigationEntry.OriginalValue) switch (navigationEntry.OriginalValue)
{ {
case null: case null:

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

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic;
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;
@ -13,12 +13,10 @@ namespace Volo.Abp.EntityFrameworkCore;
public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase
{ {
private readonly IRepository<Blog, Guid> _blogRepository; private readonly IRepository<Blog, Guid> _blogRepository;
private readonly IRepository<Post, Guid> _postRepository;
public AbpEfCoreNavigationHelper_Tests() public AbpEfCoreNavigationHelper_Tests()
{ {
_blogRepository = GetRequiredService<IRepository<Blog, Guid>>(); _blogRepository = GetRequiredService<IRepository<Blog, Guid>>();
_postRepository = GetRequiredService<IRepository<Post, Guid>>();
} }
[Fact] [Fact]
@ -30,8 +28,12 @@ public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase
return; 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 () => await WithUnitOfWorkAsync(async () =>
{ {
for (var i = 0; i < 5 * 1000; i++) for (var i = 0; i < 5 * 1000; i++)
@ -40,32 +42,54 @@ public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase
new Blog(Guid.NewGuid()) new Blog(Guid.NewGuid())
{ {
Name = "Blog" + i, Name = "Blog" + i,
BlogPosts = new List<BlogPost> BlogPosts =
{ [
new BlogPost new BlogPost(Guid.NewGuid())
{ {
Post = new Post(Guid.NewGuid()) Title = "Post" + i
{
Title = "Post" + i
}
} }
} ]
}); });
} }
}); });
stopWatch.Stop(); stopWatch.Stop();
stopWatch.Elapsed.ShouldBeLessThan(TimeSpan.FromSeconds(10)); stopWatch.Elapsed.ShouldBeLessThan(batchUpdateTime);
stopWatch.Restart(); stopWatch.Restart();
var blogs = await _blogRepository.GetListAsync(includeDetails: true); var blogs = await _blogRepository.GetListAsync(includeDetails: true);
var posts = await _postRepository.GetListAsync(includeDetails: true);
blogs.Count.ShouldBe(5 * 1000); blogs.Count.ShouldBe(5 * 1000);
blogs.SelectMany(x => x.BlogPosts.Select(y => y.Post)).Count().ShouldBe(5 * 1000); blogs.SelectMany(x => x.BlogPosts).Count().ShouldBe(5 * 1000);
posts.Count.ShouldBe(5 * 1000); stopWatch.Stop();
posts.SelectMany(x => x.BlogPosts.Select(y => y.Blog)).Count().ShouldBe(5 * 1000); 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.Stop();
stopWatch.Elapsed.ShouldBeLessThan(TimeSpan.FromSeconds(1)); stopWatch.Elapsed.ShouldBeLessThan(queryTime);
} }
} }

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

@ -56,11 +56,7 @@ public class AbpEntityFrameworkCoreTestModule : AbpModule
options.Entity<Blog>(opt => options.Entity<Blog>(opt =>
{ {
opt.DefaultWithDetailsFunc = q => q.Include(p => p.BlogPosts).ThenInclude(bp => bp.Post); opt.DefaultWithDetailsFunc = q => q.Include(p => p.BlogPosts);
});
options.Entity<Post>(opt =>
{
opt.DefaultWithDetailsFunc = q => q.Include(p => p.BlogPosts).ThenInclude(bp => bp.Blog);
}); });
}); });

10
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs

@ -31,7 +31,6 @@ public class TestMigrationsDbContext : AbpDbContext<TestMigrationsDbContext>
public DbSet<AppEntityWithNavigationsForeign> AppEntityWithNavigationsForeign { get; set; } public DbSet<AppEntityWithNavigationsForeign> AppEntityWithNavigationsForeign { get; set; }
public DbSet<Blog> Blogs { get; set; } public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<BlogPost> BlogPosts { get; set; } public DbSet<BlogPost> BlogPosts { get; set; }
public TestMigrationsDbContext(DbContextOptions<TestMigrationsDbContext> options) public TestMigrationsDbContext(DbContextOptions<TestMigrationsDbContext> options)
@ -110,18 +109,9 @@ public class TestMigrationsDbContext : AbpDbContext<TestMigrationsDbContext>
.HasForeignKey(bp => bp.BlogId); .HasForeignKey(bp => bp.BlogId);
}); });
modelBuilder.Entity<Post>(b =>
{
b.ConfigureByConvention();
b.HasMany(bp => bp.BlogPosts)
.WithOne(bp => bp.Post)
.HasForeignKey(bp => bp.PostId);
});
modelBuilder.Entity<BlogPost>(b => modelBuilder.Entity<BlogPost>(b =>
{ {
b.ConfigureByConvention(); b.ConfigureByConvention();
b.HasKey(p => new { p.BlogId, p.PostId });
}); });
} }
} }

19
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs

@ -17,28 +17,15 @@ public class Blog : FullAuditedAggregateRoot<Guid>
public List<BlogPost> BlogPosts { get; set; } public List<BlogPost> BlogPosts { get; set; }
} }
public class Post : FullAuditedAggregateRoot<Guid> public class BlogPost : Entity<Guid>
{ {
public Post(Guid id) public BlogPost(Guid id)
: base(id) : base(id)
{ {
} }
public string Title { get; set; }
public List<BlogPost> BlogPosts { get; set; }
}
public class BlogPost : Entity
{
public Guid BlogId { get; set; } public Guid BlogId { get; set; }
public Blog Blog { get; set; } public Blog Blog { get; set; }
public Guid PostId { get; set; } public string Title { get; set; }
public Post Post { get; set; }
public override object[] GetKeys()
{
return new object[] { BlogId, PostId };
}
} }

10
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs

@ -38,7 +38,6 @@ public class TestAppDbContext : AbpDbContext<TestAppDbContext>, IThirdDbContext,
public DbSet<AppEntityWithNavigationsForeign> AppEntityWithNavigationsForeign { get; set; } public DbSet<AppEntityWithNavigationsForeign> AppEntityWithNavigationsForeign { get; set; }
public DbSet<Blog> Blogs { get; set; } public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<BlogPost> BlogPosts { get; set; } public DbSet<BlogPost> BlogPosts { get; set; }
public TestAppDbContext(DbContextOptions<TestAppDbContext> options) public TestAppDbContext(DbContextOptions<TestAppDbContext> options)
@ -136,18 +135,9 @@ public class TestAppDbContext : AbpDbContext<TestAppDbContext>, IThirdDbContext,
.HasForeignKey(bp => bp.BlogId); .HasForeignKey(bp => bp.BlogId);
}); });
modelBuilder.Entity<Post>(b =>
{
b.ConfigureByConvention();
b.HasMany(bp => bp.BlogPosts)
.WithOne(bp => bp.Post)
.HasForeignKey(bp => bp.PostId);
});
modelBuilder.Entity<BlogPost>(b => modelBuilder.Entity<BlogPost>(b =>
{ {
b.ConfigureByConvention(); b.ConfigureByConvention();
b.HasKey(p => new { p.BlogId, p.PostId });
}); });
modelBuilder.TryConfigureObjectExtensions<TestAppDbContext>(); modelBuilder.TryConfigureObjectExtensions<TestAppDbContext>();

Loading…
Cancel
Save