Browse Source

`AsNoTracking` for `Queryable` instead of `DbContext`.

pull/17421/head
maliming 3 years ago
parent
commit
fe95e8ddd0
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 7
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs
  2. 48
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs

7
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
@ -44,4 +45,10 @@ public static class EfCoreRepositoryExtensions
throw new ArgumentException("Given repository does not implement " + typeof(IEfCoreRepository<TEntity>).AssemblyQualifiedName, nameof(repository)); throw new ArgumentException("Given repository does not implement " + typeof(IEfCoreRepository<TEntity>).AssemblyQualifiedName, nameof(repository));
} }
public static IQueryable<TEntity> AsNoTrackingIf<TEntity>(this IQueryable<TEntity> queryable, bool condition)
where TEntity : class, IEntity
{
return condition ? queryable.AsNoTracking() : queryable;
}
} }

48
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs

@ -35,50 +35,30 @@ public class EfCoreRepository<TDbContext, TEntity> : RepositoryBase<TEntity>, IE
[Obsolete("Use GetDbContextAsync() method.")] [Obsolete("Use GetDbContextAsync() method.")]
private TDbContext GetDbContext() private TDbContext GetDbContext()
{ {
TDbContext dbContext;
// Multi-tenancy unaware entities should always use the host connection string // Multi-tenancy unaware entities should always use the host connection string
if (!EntityHelper.IsMultiTenant<TEntity>()) if (!EntityHelper.IsMultiTenant<TEntity>())
{ {
using (CurrentTenant.Change(null)) 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<TDbContext> GetDbContextAsync() protected virtual Task<TDbContext> GetDbContextAsync()
{ {
TDbContext dbContext;
// Multi-tenancy unaware entities should always use the host connection string // Multi-tenancy unaware entities should always use the host connection string
if (!EntityHelper.IsMultiTenant<TEntity>()) if (!EntityHelper.IsMultiTenant<TEntity>())
{ {
using (CurrentTenant.Change(null)) 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.")] [Obsolete("Use GetDbSetAsync() method.")]
@ -261,19 +241,19 @@ public class EfCoreRepository<TDbContext, TEntity> : RepositoryBase<TEntity>, IE
{ {
return includeDetails return includeDetails
? await (await WithDetailsAsync()).ToListAsync(GetCancellationToken(cancellationToken)) ? await (await WithDetailsAsync()).ToListAsync(GetCancellationToken(cancellationToken))
: await (await GetDbSetAsync()).ToListAsync(GetCancellationToken(cancellationToken)); : await (await GetQueryableAsync()).ToListAsync(GetCancellationToken(cancellationToken));
} }
public async override Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default) public async override Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default)
{ {
return includeDetails return includeDetails
? await (await WithDetailsAsync()).Where(predicate).ToListAsync(GetCancellationToken(cancellationToken)) ? 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<long> GetCountAsync(CancellationToken cancellationToken = default) public async override Task<long> GetCountAsync(CancellationToken cancellationToken = default)
{ {
return await (await GetDbSetAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); return await (await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken));
} }
public async override Task<List<TEntity>> GetPagedListAsync( public async override Task<List<TEntity>> GetPagedListAsync(
@ -285,7 +265,7 @@ public class EfCoreRepository<TDbContext, TEntity> : RepositoryBase<TEntity>, IE
{ {
var queryable = includeDetails var queryable = includeDetails
? await WithDetailsAsync() ? await WithDetailsAsync()
: await GetDbSetAsync(); : await GetQueryableAsync();
return await queryable return await queryable
.OrderByIf<TEntity, IQueryable<TEntity>>(!sorting.IsNullOrWhiteSpace(), sorting) .OrderByIf<TEntity, IQueryable<TEntity>>(!sorting.IsNullOrWhiteSpace(), sorting)
@ -296,12 +276,12 @@ public class EfCoreRepository<TDbContext, TEntity> : RepositoryBase<TEntity>, IE
[Obsolete("Use GetQueryableAsync method.")] [Obsolete("Use GetQueryableAsync method.")]
protected override IQueryable<TEntity> GetQueryable() protected override IQueryable<TEntity> GetQueryable()
{ {
return DbSet.AsQueryable(); return DbSet.AsQueryable().AsNoTrackingIf(IsReadOnly);
} }
public async override Task<IQueryable<TEntity>> GetQueryableAsync() public async override Task<IQueryable<TEntity>> GetQueryableAsync()
{ {
return (await GetDbSetAsync()).AsQueryable(); return (await GetDbSetAsync()).AsQueryable().AsNoTrackingIf(IsReadOnly);
} }
protected async override Task SaveChangesAsync(CancellationToken cancellationToken) protected async override Task SaveChangesAsync(CancellationToken cancellationToken)
@ -318,7 +298,7 @@ public class EfCoreRepository<TDbContext, TEntity> : RepositoryBase<TEntity>, IE
? await (await WithDetailsAsync()) ? await (await WithDetailsAsync())
.Where(predicate) .Where(predicate)
.SingleOrDefaultAsync(GetCancellationToken(cancellationToken)) .SingleOrDefaultAsync(GetCancellationToken(cancellationToken))
: await (await GetDbSetAsync()) : await (await GetQueryableAsync())
.Where(predicate) .Where(predicate)
.SingleOrDefaultAsync(GetCancellationToken(cancellationToken)); .SingleOrDefaultAsync(GetCancellationToken(cancellationToken));
} }
@ -493,7 +473,9 @@ public class EfCoreRepository<TDbContext, TEntity, TKey> : EfCoreRepository<TDbC
{ {
return includeDetails return includeDetails
? await (await WithDetailsAsync()).OrderBy(e => e.Id).FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken)) ? await (await WithDetailsAsync()).OrderBy(e => 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) public virtual async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)

Loading…
Cancel
Save