【问题标题】:How to ignore softDelete query filter for included entities using a Repository?如何使用存储库忽略包含实体的 softDelete 查询过滤器?
【发布时间】:2021-08-06 08:13:16
【问题描述】:

我为我的项目创建了一个使用 EfCore5 的 DataLayer,我将我的 DbContext 配置为处理 softDelete 记录:

//DbContext    
modelBuilder.Entity<EntityName>().HasQueryFilter(p => !p.Deleted);

在我的存储库中:

   // Repository Interface
    public interface IRepository<T,TKey> where T : class
    {
        ICollection<T> FindAll(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IIncludableQueryable<T, object>> include = null, bool hideDeleted = true);
    }

   // Repository
   public class Repository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>
    {
        public ICollection<TEntity> FindAll(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null, bool hideDeleted = true)
        {
            using var db = new TEGVContext();
            IQueryable<TEntity> query = db.Set<TEntity>();
            if (!hideDeleted)
                query = query.IgnoreQueryFilters();

            if (include != null)
                query = hideDeleted ? include(query) : include(query).IgnoreQueryFilters();

            return filter == null
                ? query.ToList()
                : query.Where(filter).ToList();
        }
    }

在控制器中:

 var model = _Repo.FindById(id, include: a => a
                        .Include(x => x.Entity2).ThenInclude(l => l.Entity2_1)
                        .Include(x => x.Entity3).ThenInclude(l => l.Entity3_1), false);

在我的代码中,IgnoreQueryFilters 适用于主实体,但不适用于 Include 和 ThenInclude,include 中的被调用实体仍适用 queryFilter。

如何使我的代码能够忽略所选包含的查询过滤器?有没有更好的方法来做到这一点?

【问题讨论】:

  • 您是为所有实体还是只为根实体注册了查询过滤器?
  • 我在 DbContext 中为所有必需的实体注册了查询过滤器,就像我在上面添加的一样。

标签: c# entity-framework asp.net-core


【解决方案1】:

IgnoreQueryFilters 是一个查询级选项,影响查询中的所有实体。没有选项可以仅针对查询中的某些实体关闭查询过滤器。

你为什么要写

var model = _Repo.FindById(id, include: a => a
                        .Include(x => x.Entity2).ThenInclude(l => l.Entity2_1)
                        .Include(x => x.Entity3).ThenInclude(l => l.Entity3_1), false);

而不是更直接的

var model = _Repo.FindById(id)
                 .IgnoreQueryFilters()
                 .Include(x => x.Entity2).ThenInclude(l => l.Entity2_1)
                 .Include(x => x.Entity3).ThenInclude(l => l.Entity3_1)
                 .ToList();

你会通过让你的存储库包装器返回一个 IQueryable 来获得?或者

var model = db.Entity1
              .IgnoreQueryFilters()
              .Where(e => e.Id == id)
              .Include(x => x.Entity2).ThenInclude(l => l.Entity2_1)
              .Include(x => x.Entity3).ThenInclude(l => l.Entity3_1)
              .ToList();

您是通过完全删除自定义存储库包装器获得的吗?

【讨论】:

  • 感谢您的回复。您的解决方案在某种程度上可能是有效的,但在我的情况下,我不想将 dbContext 暴露给其他项目并决定使用自定义 repo。一切都很好,直到我偶然发现了这个 queryfilter 问题,我想知道是否有一个调整可以让我免于更改整个项目,这将是一个巨大的变化。
  • 只要您将条件正确地组合到单个查询中,使用回购应该无关紧要。
猜你喜欢
  • 2016-07-17
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 2017-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多