693 lines
23 KiB
C#
693 lines
23 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Linq.Expressions;
|
||
using System.Reflection;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using AutoMapper;
|
||
using IRaCIS.Core.Domain.Models;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||
using AutoMapper.QueryableExtensions;
|
||
using EFCore.BulkExtensions;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using IRaCIS.Core.Infrastructure;
|
||
using IRaCIS.Core.Infrastructure.Extention;
|
||
using Microsoft.Extensions.Localization;
|
||
|
||
namespace IRaCIS.Core.Infra.EFCore
|
||
{
|
||
public interface IRepository<TEntity> : ICommandRepository<TEntity>, IQueryRepository<TEntity> where TEntity : Entity
|
||
{
|
||
IRaCISDBContext _dbContext { get; set; }
|
||
|
||
}
|
||
|
||
|
||
public class Repository<TEntity> : IRepository<TEntity>
|
||
where TEntity : Entity, new()
|
||
{
|
||
|
||
public IMapper _mapper { get; set; }
|
||
public IRaCISDBContext _dbContext { get; set; }
|
||
|
||
public IStringLocalizer _localizer { get; set; }
|
||
|
||
public DbSet<TEntity> _dbSet => _dbContext.Set<TEntity>();
|
||
|
||
public IUserInfo _userInfo { get; set; }
|
||
|
||
public Repository(IRaCISDBContext dbContext, IMapper mapper, IUserInfo userInfo, IStringLocalizer localizer)
|
||
{
|
||
_localizer = localizer;
|
||
_dbContext = dbContext;
|
||
_mapper = mapper;
|
||
_userInfo = userInfo;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
#region 异步 EF 跟踪 添加
|
||
public async Task<IEnumerable<TEntity>> AddRangeAsync(IEnumerable<TEntity> entities, bool autoSave = false)
|
||
{
|
||
|
||
await _dbSet.AddRangeAsync(entities).ConfigureAwait(false);
|
||
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
return entities;
|
||
}
|
||
|
||
/// <summary>EF跟踪方式 添加</summary>
|
||
public async ValueTask<TEntity> AddAsync(TEntity entity, bool autoSave = false)
|
||
{
|
||
|
||
await _dbSet.AddAsync(entity).ConfigureAwait(false);
|
||
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
return entity;
|
||
}
|
||
|
||
|
||
|
||
public async Task<TEntity> InsertFromDTOAsync<TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
|
||
await _dbContext.EntityVerifyAsync(true, verify);
|
||
|
||
var entity = _mapper.Map<TEntity>(from);
|
||
|
||
entity = await AddAsync(entity, autoSave);
|
||
|
||
|
||
return entity;
|
||
|
||
}
|
||
#endregion
|
||
|
||
|
||
#region 异步 EF 跟踪 部分字段更新
|
||
|
||
|
||
/// <summary>用前端传递的视图模型字段,更新,同时返回数据库该条记录的原始信息,方便对比某些字段是否更改,进行相应的逻辑操作</summary>
|
||
|
||
public async Task<TEntity> UpdateFromDTOAsync<TFrom>(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
|
||
var entity = _mapper.Map<TEntity>(from);
|
||
|
||
//await EntityVerifyAsync(false, verify, entity.Id);
|
||
|
||
await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
|
||
|
||
var dbEntity = await _dbSet.IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false);
|
||
|
||
if (dbEntity == null)
|
||
{
|
||
|
||
throw new BusinessValidationFailedException(_localizer["Repository_UpdateError"]);
|
||
}
|
||
|
||
var dbBeforEntity = dbEntity.Clone();
|
||
|
||
|
||
_mapper.Map(from, dbEntity);
|
||
|
||
|
||
//DTO null 属性不更新 防止意外操作,导致保存数据错误,或者 add 和update 用一个模型,更新的时候,只传递了部分字段,导致,不想更新的字段,因为没传递值,用null覆盖了
|
||
// Guid?属性 为null 时 映射到 Guid 时 默认会变成 Guid.Empty
|
||
if (ignoreDtoNullProperty)
|
||
{
|
||
var dbEntityProp = typeof(TEntity).GetProperties();
|
||
foreach (var propertyInfo in from.GetType().GetProperties())
|
||
{
|
||
if (propertyInfo.GetValue(from) == null && dbEntityProp.Any(t => t.Name == propertyInfo.Name))
|
||
{
|
||
_dbContext.Entry(dbEntity).Property(propertyInfo.Name).IsModified = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
|
||
return dbBeforEntity;
|
||
}
|
||
|
||
|
||
|
||
/// <summary> EF跟踪方式 生成 部分字段更新, 跟踪的实体仅有修改的属性的值有具体意义,没有从数据库查询完整的实体</summary>
|
||
|
||
public async Task UpdatePartialNoQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
|
||
await _dbContext.EntityVerifyAsync(false, verify, id);
|
||
|
||
var entity = new TEntity() { Id = id };
|
||
|
||
_dbContext.EntityModifyPartialFiled(entity, updateFactory);
|
||
|
||
|
||
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
}
|
||
|
||
|
||
/// <summary> EF跟踪方式 生成 部分字段立即更新,默认会去处理更新更新人 更新时间 </summary>
|
||
public async Task<bool> UpdatePartialNowNoQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
|
||
params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
await _dbContext.EntityVerifyAsync(false, verify, id);
|
||
|
||
var entity = new TEntity() { Id = id };
|
||
|
||
_dbContext.EntityModifyPartialFiled(entity, updateFactory);
|
||
|
||
return await SaveChangesAsync(true);
|
||
}
|
||
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
#region 异步 EF 跟踪 自动生成 更新 和删除语句
|
||
|
||
|
||
/// <summary>EF跟踪方式 更新,全字段更新 不好</summary>
|
||
public async Task<bool> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
_dbSet.Update(entity);
|
||
|
||
return await SaveChangesAsync(autoSave);
|
||
}
|
||
|
||
|
||
/// <summary>EF跟踪方式 外层先有查询好的完成实体,再更新部分字段 稽查的时候需要完整的实体信息</summary>
|
||
public async Task<bool> UpdateAsync(TEntity waitModifyEntity, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
|
||
_dbContext.EntityModifyPartialFiled(waitModifyEntity, updateFactory);
|
||
|
||
return await SaveChangesAsync(autoSave);
|
||
|
||
}
|
||
|
||
|
||
/// <summary>EF跟踪方式 先查询出来,再更新部分字段 当在同一个事务里面需要更新同一个实体两次,请使用该方法,否则会因为重复跟踪同一个实体报错 (稽查的时候需要完整的实体信息)</summary>
|
||
public async Task<TEntity> UpdatePartialFromQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
|
||
bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
|
||
//var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
|
||
|
||
|
||
//不跟踪 查询出来的实体就是Detached
|
||
var searchEntity = await _dbSet.FindAsync( id);
|
||
|
||
if (searchEntity == null)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["Repository_UpdateError"]);
|
||
}
|
||
|
||
_dbContext.EntityModifyPartialFiled(searchEntity, updateFactory);
|
||
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
return searchEntity;
|
||
}
|
||
|
||
public async Task UpdatePartialFromQueryAsync(Expression<Func<TEntity, bool>> updateFilter,
|
||
Expression<Func<TEntity, TEntity>> updateFactory,
|
||
bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default)
|
||
{
|
||
if (updateFilter == null)
|
||
{
|
||
throw new ArgumentException("更新过滤条件不允许为空", nameof(updateFilter));
|
||
}
|
||
var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
|
||
|
||
var searchEntityList = await query.Where(updateFilter).ToListAsync();
|
||
|
||
foreach (var needUpdateEntity in searchEntityList)
|
||
{
|
||
await UpdateAsync(needUpdateEntity, updateFactory, false);
|
||
}
|
||
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>EF跟踪方式 删除</summary>
|
||
public async Task<bool> DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
_dbSet.Remove(entity);
|
||
|
||
return await SaveChangesAsync(autoSave);
|
||
}
|
||
|
||
|
||
/// <summary>EF跟踪方式(查询出来,再删除 浪费性能,但是稽查 或者触发某些操作时,需要知道数据库实体信息 不可避免用这种)</summary>
|
||
public async Task<TEntity> DeleteFromQueryAsync(Guid id, bool autoSave = false, bool ignoreQueryFilter = false)
|
||
{
|
||
var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
|
||
|
||
var waitDelete = await query.Where(t => t.Id == id).FirstOrDefaultAsync();
|
||
|
||
if (waitDelete == null)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["Repository_DeleteError"]);
|
||
}
|
||
|
||
await DeleteAsync(waitDelete, autoSave);
|
||
|
||
return waitDelete;
|
||
}
|
||
|
||
|
||
/// <summary>批量删除,EF跟踪方式(所有查询出来,再删除 浪费性能,但是稽查 或者触发某些操作时,需要知道数据库实体信息 不可避免用这种)</summary>
|
||
public async Task<List<TEntity>> DeleteFromQueryAsync(Expression<Func<TEntity, bool>> deleteFilter, bool autoSave = false, bool ignoreQueryFilter = false)
|
||
{
|
||
var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
|
||
var waitDeleteList = await query.Where(deleteFilter).ToListAsync();
|
||
|
||
_dbSet.RemoveRange(waitDeleteList);
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
return waitDeleteList;
|
||
|
||
}
|
||
|
||
public async Task<List<TEntity>> SoftDeleteFromQueryAsync(Expression<Func<TEntity, bool>> deleteFilter, bool autoSave = false, bool ignoreQueryFilter = false)
|
||
{
|
||
var query = ignoreQueryFilter ? _dbSet.IgnoreQueryFilters() : _dbSet;
|
||
var waitDeleteList = await query.Where(deleteFilter).ToListAsync();
|
||
|
||
foreach (var deleteItem in waitDeleteList)
|
||
{
|
||
if (deleteItem is ISoftDelete softDeleteItem)
|
||
{
|
||
softDeleteItem.IsDeleted = true;
|
||
}
|
||
}
|
||
|
||
await SaveChangesAsync(autoSave);
|
||
|
||
return waitDeleteList;
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
#region 不走EF 跟踪机制的删除 更新 以及批量操作
|
||
|
||
/// <summary>批量删除,相当于原生sql, 没用EF跟踪方式(所有查询出来,再删除 浪费性能)</summary>
|
||
public async Task<bool> BatchDeleteNoTrackingAsync(Expression<Func<TEntity, bool>> deleteFilter)
|
||
{
|
||
|
||
return await _dbContext.BatchDeleteNoTrackingAsync(deleteFilter);
|
||
|
||
}
|
||
|
||
|
||
/// <summary>批量更新,相当于原生sql, 没用EF跟踪方式(所有查询出来,再更新 浪费性能)</summary>
|
||
public async Task<bool> BatchUpdateNoTrackingAsync(Expression<Func<TEntity, bool>> where,
|
||
Expression<Func<TEntity, TEntity>> updateFactory)
|
||
{
|
||
|
||
return await _dbContext.BatchUpdateNoTrackingAsync(where, updateFactory,_userInfo.Id);
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
|
||
#region 保存 、忽略 、验证
|
||
public async Task<TEntity> InsertOrUpdateAsync<TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
var entity = _mapper.Map<TEntity>(from);
|
||
|
||
|
||
if (entity.Id == Guid.Empty)
|
||
{
|
||
return await InsertFromDTOAsync(from, autoSave, verify);
|
||
}
|
||
else
|
||
{
|
||
return await UpdateFromDTOAsync(from, autoSave, false, verify);
|
||
}
|
||
}
|
||
|
||
|
||
private async Task<bool> SaveChangesAsync(bool autoSave)
|
||
{
|
||
if (autoSave)
|
||
{
|
||
return await SaveChangesAsync();
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 忽略空值属性
|
||
/// </summary>
|
||
/// <param name="entity"></param>
|
||
/// <param name="ignoreNullValues"></param>
|
||
private void IgnoreNullValues(ref TEntity entity, bool? ignoreNullValues = null)
|
||
{
|
||
var isIgnore = ignoreNullValues;
|
||
if (isIgnore == false) return;
|
||
|
||
// 获取所有的属性
|
||
var properties = _dbSet.EntityType.GetProperties();
|
||
if (properties == null) return;
|
||
|
||
foreach (var propety in properties)
|
||
{
|
||
var entityProperty = _dbContext.Entry(entity).Property(propety.Name);
|
||
var propertyValue = entityProperty?.CurrentValue;
|
||
var propertyType = entityProperty?.Metadata?.PropertyInfo?.PropertyType;
|
||
|
||
// 判断是否是无效的值,比如为 null,默认时间,以及空 Guid 值
|
||
var isInvalid = propertyValue == null
|
||
|| (propertyType == typeof(DateTime) && propertyValue?.ToString() == new DateTime().ToString())
|
||
|| (propertyType == typeof(DateTimeOffset) && propertyValue?.ToString() == new DateTimeOffset().ToString())
|
||
|| (propertyType == typeof(Guid) && propertyValue?.ToString() == Guid.Empty.ToString());
|
||
|
||
if (isInvalid && entityProperty != null)
|
||
{
|
||
entityProperty.IsModified = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
public async Task<bool> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
|
||
return await _dbContext.SaveChangesAsync(cancellationToken) > 0;
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region 不常用
|
||
/// <summary>EF跟踪方式 生成 部分字段更新 (只更新传递的字段名 new[] {nameof(User.Name), nameof(User.Age))</summary>
|
||
public async Task<TEntity> UpdatePartialFieldsAsync(TEntity entity, string[] propertyNames,
|
||
bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
|
||
await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
|
||
|
||
var entityEntry = _dbContext.Entry(entity);
|
||
entityEntry.State = EntityState.Detached;
|
||
|
||
|
||
foreach (var propertyName in propertyNames)
|
||
{
|
||
_dbContext.Entry(entity).Property(propertyName).IsModified = true;
|
||
}
|
||
|
||
// 忽略空值
|
||
IgnoreNullValues(ref entity, ignoreEntityNullProperty);
|
||
|
||
return entityEntry.Entity;
|
||
}
|
||
|
||
/// <summary>更新 排除某些字段的更新 排除方式: new[] {nameof(User.Name), nameof(User.Age)</summary>
|
||
public async Task<TEntity> UpdateExcludeFields(TEntity entity, string[] propertyNames, bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
|
||
|
||
var entityEntry = _dbContext.Entry(entity);
|
||
entityEntry.State = EntityState.Modified;
|
||
|
||
|
||
foreach (var propertyName in propertyNames)
|
||
{
|
||
_dbContext.Entry(entity).Property(propertyName).IsModified = false;
|
||
}
|
||
|
||
// 忽略空值
|
||
IgnoreNullValues(ref entity, ignoreEntityNullProperty);
|
||
|
||
return entityEntry.Entity;
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
#region 异步查询
|
||
|
||
|
||
|
||
public async Task<TResult> MaxAsync<TResult>(Expression<Func<TEntity, TResult>> selector)
|
||
{
|
||
|
||
return await _dbSet.AsNoTracking().MaxAsync(selector);
|
||
}
|
||
|
||
public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> exp, bool ignoreQueryFilters = false)
|
||
{
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
return await query.AsNoTracking().AnyAsync(exp);
|
||
}
|
||
|
||
|
||
public bool Any(Expression<Func<TEntity, bool>> exp, bool ignoreQueryFilters = false)
|
||
{
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
return query.AsNoTracking().Any(exp);
|
||
}
|
||
|
||
public async Task<int> CountAsync(Expression<Func<TEntity, bool>> whereLambda = null, bool ignoreQueryFilters = false)
|
||
{
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
return whereLambda == null ? await query.AsNoTracking().CountAsync() : await query.AsNoTracking().CountAsync(whereLambda);
|
||
}
|
||
|
||
public async ValueTask<TEntity> FindAsync(Guid id, CancellationToken cancellationToken = default)
|
||
{
|
||
return await _dbContext.FindAsync<TEntity>(id);
|
||
}
|
||
|
||
//有可能是联合主键,本项目没用到,用Guid
|
||
public async ValueTask<TEntity> FindAsync(object[] keyValues, CancellationToken cancellationToken)
|
||
{
|
||
return await _dbContext.FindAsync<TEntity>(keyValues);
|
||
}
|
||
|
||
|
||
public async Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> exp = null, bool isTracking = false, bool ignoreQueryFilters = false)
|
||
{
|
||
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (!isTracking)
|
||
{
|
||
query = query.AsNoTracking();
|
||
}
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
var entity = await query.FirstOrDefaultAsync(exp);
|
||
|
||
if (entity is null)
|
||
{
|
||
throw new QueryBusinessObjectNotExistException($"The query object {typeof(TEntity).Name} does not exist in database, Please check the query parameters");
|
||
}
|
||
else
|
||
{
|
||
return entity;
|
||
}
|
||
|
||
}
|
||
|
||
public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> exp = null, bool ignoreQueryFilters = false)
|
||
{
|
||
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
|
||
if (exp != null)
|
||
{
|
||
query = query.Where(exp);
|
||
}
|
||
|
||
return await query.FirstOrDefaultAsync().ConfigureAwait(false);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 不跟踪
|
||
/// </summary>
|
||
/// <param name="exp"></param>
|
||
/// <param name="ignoreQueryFilters"></param>
|
||
/// <returns></returns>
|
||
public async Task<TEntity> FirstOrDefaultNoTrackingAsync(Expression<Func<TEntity, bool>> exp = null, bool ignoreQueryFilters = false)
|
||
{
|
||
|
||
var query = _dbSet.AsNoTracking().AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
|
||
if (exp != null)
|
||
{
|
||
query = query.Where(exp);
|
||
}
|
||
|
||
return await query.AsNoTracking().FirstOrDefaultAsync().ConfigureAwait(false);
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
#region 非异步部分
|
||
|
||
public TEntity ImageFind(Guid id, Type type)
|
||
{
|
||
//重传的时候 状态为修改 上传的时候状态为添加 内存中有,就不要重复查询数据库了
|
||
var list = _dbContext.ChangeTracker.Entries()
|
||
.Where(u => (u.State == EntityState.Added || u.State == EntityState.Modified) && (u.Entity.GetType() == type)).Select(t => t.Entity as TEntity);
|
||
|
||
var entity = list.FirstOrDefault(t => t.Id == id);
|
||
|
||
if (entity == null)
|
||
{
|
||
return _dbSet.FirstOrDefault(t => t.Id == id);
|
||
}
|
||
else
|
||
{
|
||
return entity;
|
||
}
|
||
|
||
}
|
||
|
||
public IQueryable<TEntity> AsQueryable(bool ignoreQueryFilters = false)
|
||
{
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
return query.AsNoTracking();
|
||
}
|
||
|
||
public IQueryable<TResult> Select<TResult>(Expression<Func<TEntity, TResult>> selector)
|
||
{
|
||
return _dbSet.AsNoTracking().Select(selector);
|
||
}
|
||
|
||
public IQueryable<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> filter)
|
||
{
|
||
return condition ? _dbSet.AsNoTracking().Where(filter) : _dbSet.AsNoTracking();
|
||
}
|
||
|
||
public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> exp = null, bool isTraking = false, bool ignoreQueryFilters = false)
|
||
{
|
||
IQueryable<TEntity> query = _dbSet;
|
||
|
||
if (!isTraking)
|
||
{
|
||
query = query.AsNoTracking();
|
||
}
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
if (exp != null)
|
||
{
|
||
query = query.Where(exp);
|
||
}
|
||
return query;
|
||
}
|
||
|
||
public EntityEntry Entry(TEntity t)
|
||
{
|
||
return _dbContext.Entry(t);
|
||
}
|
||
|
||
public EntityEntry<TEntity> Attach(TEntity entity)
|
||
{
|
||
return _dbSet.Attach(entity);
|
||
}
|
||
|
||
public void Detached(TEntity t)
|
||
{
|
||
_dbContext.Entry(t).State = EntityState.Detached;
|
||
}
|
||
|
||
|
||
// automapper 相关
|
||
public IQueryable<TDestination> ProjectTo<TDestination>(IConfigurationProvider configuration, object parameters, params Expression<Func<TDestination, object>>[] membersToExpand)
|
||
{
|
||
return _dbSet.AsNoTracking().ProjectTo(configuration, parameters, membersToExpand);
|
||
}
|
||
|
||
public IQueryable<TDestination> ProjectTo<TDestination>(IConfigurationProvider configuration, params Expression<Func<TDestination, object>>[] membersToExpand)
|
||
{
|
||
return _dbSet.AsNoTracking().ProjectTo(configuration, membersToExpand);
|
||
}
|
||
|
||
public IQueryable<TDestination> ProjectTo<TDestination>(IConfigurationProvider configuration, IDictionary<string, object> parameters, params string[] membersToExpand)
|
||
{
|
||
return _dbSet.AsNoTracking().ProjectTo<TDestination>(configuration, parameters, membersToExpand);
|
||
}
|
||
|
||
|
||
#endregion
|
||
}
|
||
|
||
}
|