From fe95e8ddd0d236dc4003d96a1a90cb64f6f7c619 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 24 Aug 2023 10:29:35 +0800 Subject: [PATCH] `AsNoTracking` for `Queryable` instead of `DbContext`. --- .../EfCoreRepositoryExtensions.cs | 7 +++ .../EntityFrameworkCore/EfCoreRepository.cs | 48 ++++++------------- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs index 94dba628d7..614ba135ff 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Entities; @@ -44,4 +45,10 @@ public static class EfCoreRepositoryExtensions throw new ArgumentException("Given repository does not implement " + typeof(IEfCoreRepository).AssemblyQualifiedName, nameof(repository)); } + + public static IQueryable AsNoTrackingIf(this IQueryable queryable, bool condition) + where TEntity : class, IEntity + { + return condition ? queryable.AsNoTracking() : queryable; + } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs index 2f89ac2b8a..b881c07245 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs @@ -35,50 +35,30 @@ public class EfCoreRepository : RepositoryBase, IE [Obsolete("Use GetDbContextAsync() method.")] private TDbContext GetDbContext() { - TDbContext dbContext; // Multi-tenancy unaware entities should always use the host connection string if (!EntityHelper.IsMultiTenant()) { using (CurrentTenant.Change(null)) { - dbContext = _dbContextProvider.GetDbContext(); + return _dbContextProvider.GetDbContext(); } } - else - { - dbContext = _dbContextProvider.GetDbContext(); - } - - if (IsReadOnly) - { - dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - } - return dbContext; + return _dbContextProvider.GetDbContext(); } - protected virtual async Task GetDbContextAsync() + protected virtual Task GetDbContextAsync() { - TDbContext dbContext; // Multi-tenancy unaware entities should always use the host connection string if (!EntityHelper.IsMultiTenant()) { using (CurrentTenant.Change(null)) { - dbContext = await _dbContextProvider.GetDbContextAsync(); + return _dbContextProvider.GetDbContextAsync(); } } - else - { - dbContext = await _dbContextProvider.GetDbContextAsync(); - } - - if (IsReadOnly) - { - dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - } - return dbContext; + return _dbContextProvider.GetDbContextAsync(); } [Obsolete("Use GetDbSetAsync() method.")] @@ -261,19 +241,19 @@ public class EfCoreRepository : RepositoryBase, IE { return includeDetails ? await (await WithDetailsAsync()).ToListAsync(GetCancellationToken(cancellationToken)) - : await (await GetDbSetAsync()).ToListAsync(GetCancellationToken(cancellationToken)); + : await (await GetQueryableAsync()).ToListAsync(GetCancellationToken(cancellationToken)); } public async override Task> GetListAsync(Expression> predicate, bool includeDetails = false, CancellationToken cancellationToken = default) { return includeDetails ? await (await WithDetailsAsync()).Where(predicate).ToListAsync(GetCancellationToken(cancellationToken)) - : await (await GetDbSetAsync()).Where(predicate).ToListAsync(GetCancellationToken(cancellationToken)); + : await (await GetQueryableAsync()).Where(predicate).ToListAsync(GetCancellationToken(cancellationToken)); } public async override Task GetCountAsync(CancellationToken cancellationToken = default) { - return await (await GetDbSetAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); } public async override Task> GetPagedListAsync( @@ -285,7 +265,7 @@ public class EfCoreRepository : RepositoryBase, IE { var queryable = includeDetails ? await WithDetailsAsync() - : await GetDbSetAsync(); + : await GetQueryableAsync(); return await queryable .OrderByIf>(!sorting.IsNullOrWhiteSpace(), sorting) @@ -296,12 +276,12 @@ public class EfCoreRepository : RepositoryBase, IE [Obsolete("Use GetQueryableAsync method.")] protected override IQueryable GetQueryable() { - return DbSet.AsQueryable(); + return DbSet.AsQueryable().AsNoTrackingIf(IsReadOnly); } public async override Task> GetQueryableAsync() { - return (await GetDbSetAsync()).AsQueryable(); + return (await GetDbSetAsync()).AsQueryable().AsNoTrackingIf(IsReadOnly); } protected async override Task SaveChangesAsync(CancellationToken cancellationToken) @@ -318,7 +298,7 @@ public class EfCoreRepository : RepositoryBase, IE ? await (await WithDetailsAsync()) .Where(predicate) .SingleOrDefaultAsync(GetCancellationToken(cancellationToken)) - : await (await GetDbSetAsync()) + : await (await GetQueryableAsync()) .Where(predicate) .SingleOrDefaultAsync(GetCancellationToken(cancellationToken)); } @@ -493,7 +473,9 @@ public class EfCoreRepository : EfCoreRepository e.Id).FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken)) - : await (await GetDbSetAsync()).FindAsync(new object[] { id }, GetCancellationToken(cancellationToken)); + : IsReadOnly + ? await (await GetQueryableAsync()).OrderBy(e => e.Id).FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken)) + : await (await GetDbSetAsync()).FindAsync(new object[] {id}, GetCancellationToken(cancellationToken)); } public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)