前言

  在项目开发中,我们很多时候都会设计  软删除、所属用户 等等一系列字段 来方便我们在业务查询的时候进行各种过滤

  然后引申的问题就是:

    在业务查询的时候,我们要如何加上这些条件?或者动态禁用某些查询条件呢?

EF Core自带的全局过滤查询功能

  EF Core提供了一个HasQueryFilter 供我们在查询的时候进行预置部分筛选条件

  例如:

      builder.HasQueryFilter(x => !x.IsDelete);

  这样查询的时候  EF Core 会自动帮我们实现过滤

  然后如果不想使用的时候可以全部忽略

    DbSet.IgnoreQueryFilters();

  咋一看 很完美

  然后我们实际操作的时候

  1.我是不是每个Entity里面是不是都要配置一次呢?

  2.我只想禁用部分筛选条件呢?

  3.我的查询条件的某些参数要动态呢?

    例如和用户相关的数据等等

    (有些人可能会说 我想办法把User的信息注入到DbContext里面不就可以了  假如我还要别的信息呢  还是接着注入?)

  这就是理论和实践之间的差距

  然后再网上找好久,找到了 EntityFramework-Plus  (开源免费)

  https://github.com/zzzprojects/EntityFramework-Plus

     官网地址: http://entityframework-plus.net/  

  内置了很多功能  本篇只针对查询过滤做说嘛

EntityFramework-Plus 查询过滤功能

  1.QueryFilterManager

  QueryFilterManager 主要用来预设全局过滤

  例如:

  QueryFilterManager.Filter<Customer>(q => q.Where(x => x.IsActive));

  var ctx = new EntitiesContext();

  QueryFilterManager.InitilizeGlobalFilter(ctx);

  这样即可。。。

  但是需要提前注意的是 QueryFilterManager 预设后是无法更改的

  无法更改这是在  谷歌的时候  作者正好回复的别人的时候看到的

  就和我们之前第三点  动态 冲突了

  然后只能再看别的方式了

  2.Filter

  Z.EntityFramework.Plus 提供了 通过DbContext 的扩展方式来进行注入筛选条件的方式

  例如:

  var ctx = new EntitiesContext();

  ctx.Filter<IAnimal>(MyEnum.EnumValue, q => q.Where(x => x.IsDomestic))

  //禁用指定键值查询条件

  ctx.Filter(MyEnum.EnumValue).Disable();

  var dogs = ctx.Dogs.ToList();

  //启用指定键值查询条件

  ctx.Filter(MyEnum.EnumValue).Enable();

  // SELECT * FROM Dog WHERE IsDomestic = true
  var dogs = ctx.Dogs.ToList();

  这样好像符合我们的需求

  3.AsNoFilter

  禁用条件

  例如: 

  var ctx = new EntitiesContext();

  this.Filter<Customer>(q => q.Where(x => x.IsActive));

  // SELECT * FROM Customer WHERE IsActive = true
  var list = ctx.Customers.ToList();

  // SELECT * FROM Customer
  var list = ctx.Customers.AsNoFilter().ToList();

  AsNoFilter()后如何启用  指定查询条件  作者好像没有做相应扩展 ,后面会给出对应扩展方法

-----------------------------------------------------------------------------------------------------------------------------------------------------------

说了这么多 理论补完了   实际操作的时候呢?

  1.这些条件如何注入进来呢?

  2.如何可以让我任意扩展呢?

     3.假如我们操作时通过仓储 ,而不是  直接通过DbContext 呢?

如何封装

这边演示通过我自己的开源项目做为事例:

  github  : https://github.com/wulaiwei/WorkData.Core

  主要依赖的框架

  1.AutoFac

  2.EF Core

  3.Z.EntityFramework.Plus

-----------------------------------------------------------------------------------------------------------------------------------------  

  对于我们来说 我们无论使用多少个数据筛选器  返回的都应该是同一个返回值  ,我们去看 DbContext.Filter(....)  会发现他的返回值都是 BaseQueryFilter

  针对这个  我们可以得到两条信息  我们需要 传入 DbContext  和 一个返回值为  BaseQueryFilter  的方法

  所以 我们定义如下接口 IDynamicFilter

1     public interface IDynamicFilter
2     {
3         BaseQueryFilter InitFilter(DbContext dbContext);
4     }

View Code

  这样我们这边就得到了一个标准

  例如 我们我们需要一个 所属用户和  软删除 的数据筛选器   我们只需要继承他即可

  我们如何区分他们呢?

  我们在之前使用 Z.EntityFramework.Plus  是看到了  可以设置筛选器的Key

  所以 我们也同样扩展个属性 DynamicFilterAttribute  来作为他们的名字

1     public class DynamicFilterAttribute: Attribute
2     {
3         /// <summary>
4         /// Name
5         /// </summary>
6         public string Name { get; set; }
7
8     }

View Code

  然后我们定义我们的  所属用户和  软删除 的数据筛选器  并为他们设置名称

  CreateDynamicFilter

 1  /// <summary>
 2     /// CreateDynamicFilter
 3     /// </summary>
 4     [DynamicFilter(Name = "CreateUserId")]
 5     public class CreateDynamicFilter : IDynamicFilter
 6     {
 7         /// <summary>
 8         /// InitFilter
 9         /// </summary>
10         /// <param name="dbContext"></param>
11         /// <returns></returns>
12         public BaseQueryFilter InitFilter(DbContext dbContext)
13         {
14             var workdataSession = IocManager.Instance.Resolve<IWorkDataSession>();
15             if (workdataSession == null)
16                 return dbContext
17                     .Filter<ICreate>("CreateUserId", x => x.Where(w => w.CreateUserId == string.Empty ));
18
19             return dbContext
20                 .Filter<ICreate>("CreateUserId", x => x.Where(w => w.CreateUserId == workdataSession.UserId || w.CreateUserId == ""));
21         }
22     }

View Code

  说明:

  var workdataSession = IocManager.Instance.Resolve<IWorkDataSession>();

  用来获取你所需要的 传参

  IocManager.Instance.Resolve  是WorkData  关于Ioc的封装  源码可以参见git  或者上一篇博客

  SoftDeleteDynamicFilter

 1 /// <summary>
 2     /// SoftDeleteDynamicFilter
 3     /// </summary>
 4     [DynamicFilter(Name = "SoftDelete")]
 5     public class SoftDeleteDynamicFilter: IDynamicFilter
 6     {
 7         public BaseQueryFilter InitFilter(DbContext dbContext)
 8         {
 9             return dbContext
10                 .Filter<IsSoftDelete>("SoftDelete", x => x.Where(w => !w.IsDelete));
11         }
12     }

View Code

   这样 我们所有接口 和实现定义好了 如何管理呢?

  1.将继承 IDynamicFilter 的注入到Ioc里面

 1             #region 动态审计注入
 2             var filterTypes = _typeFinder.FindClassesOfType<IDynamicFilter>();
 3
 4             foreach (var filterType in filterTypes)
 5             {
 6                 var dynamicFilterAttribute = filterType.GetCustomAttribute(typeof(DynamicFilterAttribute)) as DynamicFilterAttribute;
 7                 if (dynamicFilterAttribute == null)
 8                     continue;
 9
10                 builder.RegisterType(filterType).Named<IDynamicFilter>(dynamicFilterAttribute.Name);
11             }
12             #endregion

View Code

  说明:

  1.ITypeFinder 是从 nopcommerce 抽离出来的反射方法   已集成到WorkData  百度即可查询到相应说明文档

  2.通过 GetCustomAttribute  获取 DynamicFilterAttribute 的属性名称  作为注册到Ioc名称

  2.如何设置一个启用数据筛选器呢?我们这边定义个配置文件  通过 .net core 提供的程序进行配置文件注入

1     /// <summary>
2     /// 动态拦截器配置
3     /// </summary>
4     public class DynamicFilterConfig
5     {
6         public List<string> DynamicFilterList{ get; set; }
7     }

View Code

"DynamicFilterConfig": {

"DynamicFilterList": [ "CreateUserId", "SoftDelete" ]
}

如何注入配置文件 可以通过百度或者查看workdata源码 即可 这不做说明

  3.如何管理呢?什么时候统一添加到 DbContext呢?

  我们这边定义一个DynamicFilterManager 提供一个 字典集合 来暂存所以的 IDynamicFilter,同时提供一个方法来进行初始化值

 1     public static class DynamicFilterManager
 2     {
 3         static DynamicFilterManager()
 4         {
 5             CacheGenericDynamicFilter = new Dictionary<string, IDynamicFilter>();
 6         }
 7
 8         /// <summary>
 9         ///     CacheGenericDynamicFilter
10         /// </summary>
11         public static Dictionary<string, IDynamicFilter> CacheGenericDynamicFilter { get; set; }
12
13         /// <summary>
14         ///     AddDynamicFilter
15         /// </summary>
16         /// <param name="dbContext"></param>
17         /// <returns></returns>
18         public static void AddDynamicFilter(this DbContext dbContext)
19         {
20             if (dbContext == null) return;
21             foreach (var dynamicFilter in CacheGenericDynamicFilter) dynamicFilter.Value.InitFilter(dbContext);
22         }
23
24         /// <summary>
25         ///     AsWorkDataNoFilter
26         /// </summary>
27         /// <typeparam name="T"></typeparam>
28         /// <param name="query"></param>
29         /// <param name="context"></param>
30         /// <param name="filterStrings"></param>
31         /// <returns></returns>
32         public static IQueryable<T> AsWorkDataNoFilter<T>(this DbSet<T> query, DbContext context,
33             params object[] filterStrings) where T : class
34         {
35             var asNoFilterQueryable = query.AsNoFilter();
36
37             object query1 = asNoFilterQueryable;
38             var items = CacheGenericDynamicFilter.Where(x => filterStrings.Contains(x.Key));
39
40             query1 = items.Select(key => context.Filter(key.Key)).Where(item => item != null)
41                 .Aggregate(query1, (current, item) => (IQueryable) item.ApplyFilter<T>(current));
42             return (IQueryable<T>) query1;
43         }
44
45         /// <summary>
46         ///     SetCacheGenericDynamicFilter
47         /// </summary>
48         public static void SetCacheGenericDynamicFilter()
49         {
50             var dynamicFilterConfig = IocManager.Instance.ResolveServiceValue<DynamicFilterConfig>();
51
52             foreach (var item in dynamicFilterConfig.DynamicFilterList)
53             {
54                 var dynamicFilter = IocManager.Instance.ResolveName<IDynamicFilter>(item);
55                 CacheGenericDynamicFilter.Add(item, dynamicFilter);
56             }
57         }
58     }

View Code

  然后我们在DbContext里面的 OnModelCreating 进行初始化

 1  /// <summary>
 2         ///     重写模型创建函数
 3         /// </summary>
 4         /// <param name="modelBuilder"></param>
 5         protected override void OnModelCreating(ModelBuilder modelBuilder)
 6         {
 7             base.OnModelCreating(modelBuilder);
 8
 9             //初始化对象
10             DynamicFilterManager.SetCacheGenericDynamicFilter();
11         }

View Code

  初始化完成后如何将条件付给  DbContext 呢?

  在DynamicFilterManager 中我们提供了一个扩展方法 AddDynamicFilter 你可以在你创建 DbContext 的时候调用

 1      /// <summary>
 2         ///     AddDynamicFilter
 3         /// </summary>
 4         /// <param name="dbContext"></param>
 5         /// <returns></returns>
 6         public static void AddDynamicFilter(this DbContext dbContext)
 7         {
 8             if (dbContext == null) return;
 9             foreach (var dynamicFilter in CacheGenericDynamicFilter) dynamicFilter.Value.InitFilter(dbContext);
10         }

View Code

  在WorkData中  我们则需要在EfContextFactory 进行调用

  dbContext = _resolver.Resolve<TDbContext>();

  //初始化拦截器
  dbContext.AddDynamicFilter();

 1   /// <summary>
 2     ///     EfContextFactory
 3     /// </summary>
 4     public class EfContextFactory : IEfContextFactory
 5     {
 6         private readonly IResolver _resolver;
 7
 8         public EfContextFactory(IResolver resolver)
 9         {
10             _resolver = resolver;
11         }
12
13         /// <summary>
14         ///     default current context
15         /// </summary>
16         /// <param name="dic"></param>
17         /// <param name="tranDic"></param>
18         /// <returns></returns>
19         public TDbContext GetCurrentDbContext<TDbContext>(Dictionary<string, DbContext> dic, Dictionary<DbContext, IDbContextTransaction> tranDic)
20             where TDbContext : DbContext
21         {
22             return GetCurrentDbContext<TDbContext>(dic, tranDic, string.Empty);
23         }
24
25         /// <summary>
26         ///GetCurrentDbContext
27         /// </summary>
28         /// <typeparam name="TDbContext"></typeparam>
29         /// <param name="dic"></param>
30         /// <param name="tranDic"></param>
31         /// <param name="conString"></param>
32         /// <returns></returns>
33         public TDbContext GetCurrentDbContext<TDbContext>(Dictionary<string, DbContext> dic, Dictionary<DbContext, IDbContextTransaction> tranDic, string conString)
34             where TDbContext : DbContext
35         {
36             conString = typeof(TDbContext).ToString();
37             var dbContext = dic.ContainsKey(conString + "DbContext") ? dic[conString + "DbContext"] : null;
38             try
39             {
40                 if (dbContext != null)
41                 {
42                     return (TDbContext)dbContext;
43                 }
44             }
45             catch (Exception)
46             {
47                 dic.Remove(conString + "DbContext");
48             }
49             dbContext = _resolver.Resolve<TDbContext>();
50
51             //初始化拦截器
52             dbContext.AddDynamicFilter();
53
54             //我们在创建一个,放到数据槽中去
55             dic.Add(conString + "DbContext", dbContext);
56
57             //开始事务
58             var tran = dbContext.Database.BeginTransaction();
59             tranDic.Add(dbContext, tran);
60
61             return (TDbContext)dbContext;
62         }
63     }

View Code

  这样我们的筛选器已经全部注入完成了

  还剩下一个我们之前说的

  AsNoFilter()后如何启用  指定查询条件  作者好像没有做相应扩展 ,后面会给出对应扩展方法

  通过查看源码后 

 1     /// <summary>
 2     ///     Filter the query using context filters associated with specified keys.
 3     /// </summary>
 4     /// <typeparam name="T">The type of elements of the query.</typeparam>
 5     /// <param name="query">The query to filter using context filters associated with specified keys.</param>
 6     /// <param name="keys">
 7     ///     A variable-length parameters list containing keys associated to context filters to use to filter the
 8     ///     query.
 9     /// </param>
10     /// <returns>The query filtered using context filters associated with specified keys.</returns>
11     public static IQueryable<T> Filter<T>(this DbSet<T> query, params object[] keys) where T : class
12     {
13       BaseQueryFilterQueryable filterQueryable = QueryFilterManager.GetFilterQueryable((IQueryable) query);
14       IQueryable<T> query1 = filterQueryable != null ? (IQueryable<T>) filterQueryable.OriginalQuery : (IQueryable<T>) query;
15       return QueryFilterManager.AddOrGetFilterContext(filterQueryable != null ? filterQueryable.Context : InternalExtensions.GetDbContext<T>(query)).ApplyFilter<T>(query1, keys);
16     }

View Code

Z.EntityFramework.Plus  提供了一个 ApplyFilter  所以 我们基于这个 做个扩展

 1   /// <summary>
 2         ///     AsWorkDataNoFilter
 3         /// </summary>
 4         /// <typeparam name="T"></typeparam>
 5         /// <param name="query"></param>
 6         /// <param name="context"></param>
 7         /// <param name="filterStrings"></param>
 8         /// <returns></returns>
 9         public static IQueryable<T> AsWorkDataNoFilter<T>(this DbSet<T> query, DbContext context,
10             params object[] filterStrings) where T : class
11         {
12             var asNoFilterQueryable = query.AsNoFilter();
13
14             object query1 = asNoFilterQueryable;
15             var items = CacheGenericDynamicFilter.Where(x => filterStrings.Contains(x.Key));
16
17             query1 = items.Select(key => context.Filter(key.Key)).Where(item => item != null)
18                 .Aggregate(query1, (current, item) => (IQueryable) item.ApplyFilter<T>(current));
19             return (IQueryable<T>) query1;
20         }

View Code

这样 我们可以传入指定的筛选器名称  启用自己想要的

最终我们的仓储就变成了这样:

  1  /// <summary>
  2     ///     EfBaseRepository
  3     /// </summary>
  4     /// <typeparam name="TEntity"></typeparam>
  5     /// <typeparam name="TPrimaryKey"></typeparam>
  6     /// <typeparam name="TDbContext"></typeparam>
  7     public class EfBaseRepository<TDbContext, TEntity, TPrimaryKey> :
  8         BaseRepository<TEntity, TPrimaryKey>,
  9         IRepositoryDbConntext where TEntity : class, IAggregateRoot, IEntity<TPrimaryKey>
 10         where TDbContext : DbContext
 11     {
 12         //public IQueryable<EntityType> EntityTypes => Context.Model.EntityTypes.Where(t => t.Something == true);
 13
 14         private readonly IDbContextProvider<TDbContext> _dbContextProvider;
 15         private readonly IPredicateGroup<TEntity> _predicateGroup;
 16
 17         public EfBaseRepository(
 18             IDbContextProvider<TDbContext> dbContextProvider,
 19             IPredicateGroup<TEntity> predicateGroup)
 20         {
 21             _dbContextProvider = dbContextProvider;
 22             _predicateGroup = predicateGroup;
 23         }
 24
 25         /// <summary>
 26         ///     Gets EF DbContext object.
 27         /// </summary>
 28         public TDbContext Context => _dbContextProvider.GetContent();
 29
 30         /// <summary>
 31         ///     Gets DbSet for given entity.
 32         /// </summary>
 33         public virtual DbSet<TEntity> DbSet => Context.Set<TEntity>();
 34
 35         #region DbContext
 36
 37         /// <summary>
 38         ///     GetDbContext
 39         /// </summary>
 40         /// <returns></returns>
 41         public DbContext GetDbContext()
 42         {
 43             return Context;
 44         }
 45
 46         #endregion
 47
 48         #region Query
 49
 50
 51
 52         /// <summary>
 53         ///     FindBy
 54         /// </summary>
 55         /// <param name="primaryKey"></param>
 56         /// <returns></returns>
 57         public override TEntity FindBy(TPrimaryKey primaryKey)
 58         {
 59             var entity = DbSet.Find(primaryKey);
 60             return entity;
 61         }
 62
 63         /// <summary>
 64         /// FindBy
 65         /// </summary>
 66         /// <param name="primaryKey"></param>
 67         /// <param name="includeNames"></param>
 68         /// <returns></returns>
 69         public override TEntity FindBy(TPrimaryKey primaryKey, string[] includeNames)
 70         {
 71             var query = DbSet;
 72             foreach (var includeName in includeNames)
 73             {
 74                 query.Include(includeName);
 75             }
 76             var entity = query.Find(primaryKey);
 77             return entity;
 78         }
 79
 80         /// <summary>
 81         ///     AsNoFilterFindBy
 82         /// </summary>
 83         /// <param name="primaryKey"></param>
 84         /// <returns></returns>
 85         public override TEntity AsNoFilterFindBy(TPrimaryKey primaryKey)
 86         {
 87             var entity = DbSet.AsNoFilter()
 88                 .SingleOrDefault(x => x.Id.Equals(primaryKey));
 89             return entity;
 90         }
 91
 92         /// <summary>
 93         /// AsNoFilterFindBy
 94         /// </summary>
 95         /// <param name="primaryKey"></param>
 96         /// <param name="includeNames"></param>
 97         /// <returns></returns>
 98         public override TEntity AsNoFilterFindBy(TPrimaryKey primaryKey, string[] includeNames)
 99         {
100
101             var query = DbSet.AsNoFilter();
102             foreach (var includeName in includeNames)
103             {
104                 query.Include(includeName);
105             }
106             var entity = query.SingleOrDefault(x => x.Id.Equals(primaryKey));
107
108             return entity;
109         }
110
111
112         /// <summary>
113         ///     FindBy
114         /// </summary>
115         /// <param name="primaryKey"></param>
116         /// <param name="filterStrings"></param>
117         /// <returns></returns>
118         public override TEntity FindBy(TPrimaryKey primaryKey, params object[] filterStrings)
119         {
120             var entity = DbSet.AsWorkDataNoFilter(Context, filterStrings)
121                 .SingleOrDefault(x => x.Id.Equals(primaryKey));
122             return entity;
123         }
124
125         /// <summary>
126         /// FindBy
127         /// </summary>
128         /// <param name="primaryKey"></param>
129         /// <param name="includeNames"></param>
130         /// <param name="filterStrings"></param>
131         /// <returns></returns>
132         public override TEntity FindBy(TPrimaryKey primaryKey, string[] includeNames, params object[] filterStrings)
133         {
134             var query = DbSet.AsWorkDataNoFilter(Context, filterStrings);
135             foreach (var includeName in includeNames)
136             {
137                 query.Include(includeName);
138             }
139             var entity = query.SingleOrDefault(x => x.Id.Equals(primaryKey));
140
141             return entity;
142         }
143
144
145         /// <summary>
146         ///     GetAll
147         /// </summary>
148         /// <returns></returns>
149         public override IQueryable<TEntity> GetAll()
150         {
151             return DbSet;
152         }
153
154
155         /// <summary>
156         /// GetAll
157         /// </summary>
158         /// <param name="includeNames"></param>
159         /// <returns></returns>
160         public override IQueryable<TEntity> GetAll(string[] includeNames)
161         {
162             var query = DbSet;
163             foreach (var includeName in includeNames)
164             {
165                 query.Include(includeName);
166             }
167             return query;
168         }
169
170         /// <summary>
171         /// GetAll
172         /// </summary>
173         /// <param name="filterStrings"></param>
174         /// <returns></returns>
175         public override IQueryable<TEntity> GetAll(params object[] filterStrings)
176         {
177             return DbSet.AsWorkDataNoFilter(Context, filterStrings);
178         }
179
180         /// <summary>
181         /// GetAll
182         /// </summary>
183         /// <param name="includeNames"></param>
184         /// <param name="filterStrings"></param>
185         /// <returns></returns>
186         public override IQueryable<TEntity> GetAll(string[] includeNames, params object[] filterStrings)
187         {
188             var query = DbSet.AsWorkDataNoFilter(Context, filterStrings);
189
190             foreach (var includeName in includeNames)
191             {
192                 query.Include(includeName);
193             }
194             return query;
195         }
196
197         /// <summary>
198         /// AsNoFilterGetAll
199         /// </summary>
200         /// <returns></returns>
201         public override IQueryable<TEntity> AsNoFilterGetAll()
202         {
203             return DbSet.AsNoFilter();
204         }
205
206         /// <summary>
207         /// AsNoFilterGetAll
208         /// </summary>
209         /// <param name="includeNames"></param>
210         /// <returns></returns>
211         public override IQueryable<TEntity> AsNoFilterGetAll(string[] includeNames)
212         {
213             var query = DbSet.AsNoFilter();
214
215             foreach (var includeName in includeNames)
216             {
217                 query.Include(includeName);
218             }
219             return query;
220         }
221         #endregion
222
223         #region Insert
224
225         /// <summary>
226         ///     Insert
227         /// </summary>
228         /// <typeparam name="TEntity"></typeparam>
229         /// <param name="model"></param>
230         public override TEntity Insert(TEntity model)
231         {
232             return DbSet.Add(model).Entity;
233         }
234
235         /// <summary>
236         ///     InsertGetId
237         /// </summary>
238         /// <param name="model"></param>
239         /// <returns></returns>
240         public override TPrimaryKey InsertGetId(TEntity model)
241         {
242             model = Insert(model);
243
244             Context.SaveChanges();
245
246             return model.Id;
247         }
248
249         /// <summary>
250         ///     Insert
251         /// </summary>
252         /// <param name="entities"></param>
253         public override void Insert(IEnumerable<TEntity> entities)
254         {
255             if (entities == null)
256                 throw new ArgumentNullException(nameof(entities));
257
258             DbSet.AddRange(entities);
259
260             Context.SaveChanges();
261         }
262
263         #endregion
264
265         #region Delete
266
267         /// <summary>
268         ///     Delete
269         /// </summary>
270         /// <param name="entity"></param>
271         public override void Delete(TEntity entity)
272         {
273             DbSet.Remove(entity);
274             Context.SaveChanges();
275         }
276
277         /// <summary>
278         ///     Delete
279         /// </summary>
280         /// <param name="entities"></param>
281         public override void Delete(IEnumerable<TEntity> entities)
282         {
283             if (entities == null)
284                 throw new ArgumentNullException(nameof(entities));
285
286             DbSet.RemoveRange(entities);
287
288             Context.SaveChanges();
289         }
290
291         #endregion
292
293         #region Update
294
295         /// <summary>
296         ///     Update
297         /// </summary>
298         /// <param name="entity"></param>
299         public override void Update(TEntity entity)
300         {
301             DbSet.Update(entity);
302             Context.SaveChanges();
303         }
304
305         /// <summary>
306         ///     Update
307         /// </summary>
308         /// <param name="entities"></param>
309         public override void Update(IEnumerable<TEntity> entities)
310         {
311             if (entities == null)
312                 throw new ArgumentNullException(nameof(entities));
313
314             DbSet.UpdateRange(entities);
315
316             Context.SaveChanges();
317         }
318
319         #endregion
320     }

View Code

  说明:仓储的设计理念是从  ABP中抽离出来的 

  最后附测试  

启用的筛选器为 "CreateUserId", "SoftDelete"

 1  /// <summary>
 2         ///     Index
 3         /// </summary>
 4         /// <returns></returns>
 5         public IActionResult Index()
 6         {
 7             _baseRepository.GetAll().ToList();
 8             _baseRepository.GetAll("CreateUserId","xxx假定不存在的筛选器").ToList();
 9             _baseRepository.AsNoFilterGetAll().ToList();
10
11             _baseRepository.FindBy("1");
12             _baseRepository.FindBy("1", "CreateUserId", "xxx假定不存在的筛选器");
13             _baseRepository.AsNoFilterFindBy("1");
14             return View();
15         }

View Code

转载于:https://www.cnblogs.com/wulaiwei/p/9561830.html

EF Core 中实现 动态数据过滤器相关推荐

  1. EF Core中高效批量删除、更新数据的Zack.EFCore.Batch发布三个新特性

    Zack.EFCore.Batch是一个支持在Entity Framework Core中高效删除和更新数据的开源库.我们知道,EF Core中不支持高效的删除和更新数据,所有的更新和操作都是逐条数据 ...

  2. 第五节:EF Core中的三类事务(SaveChanges、DbContextTransaction、TransactionScope)

    一. 说明 EF版本的事务介绍详见: 第七节: EF的三种事务的应用场景和各自注意的问题(SaveChanges.DBContextTransaction.TransactionScope). 本节主 ...

  3. EF Core中避免贫血模型的三种行之有效的方法(翻译)

    [Paul Hiles: 3 ways to avoid an anemic domain model in EF Core :https://www.devtrends.co.uk/blog/3-w ...

  4. 静态页中调用动态数据的三种办法

    如果做网站还在使用动态页面并且url传一长窜值,那你就OUT了,不仅打开速度慢,而且影响SEO优化. 最近两三年,做网站都流行生成静态页了,静态页不需要经过服务器编译就直接反馈给用户,跟动态页面比有好 ...

  5. [小技巧]EF Core中如何获取上下文中操作过的实体

    原文地址:https://www.cnblogs.com/lwqlun/p/10576443.html 作者:Lamond Lu 源代码:https://github.com/lamondlu/EFC ...

  6. SQL Server中的动态数据屏蔽

    Security has been one of the prime concerns of database developers since the inception of database m ...

  7. azure云数据库_在Azure SQL数据库中实现动态数据屏蔽

    azure云数据库 In this article, we will review Dynamic Data Masking in the Azure SQL database. Dynamic Da ...

  8. python抓取网页信息_python抓取网页中的动态数据

    一.概念 网页中的许多数据并不是写死在HTML中的,而是通过js动态载入的.所以也就引出了什么是动态数据的概念,动态数据在这里指的是网页中由Javascript动态生成的页面内容,是在页面加载到浏览器 ...

  9. 如何使用 EF Core 按周 对数据分组?

    咨询区 Aza: 在 Entity Framework 6 中,我可以用 SqlFunctions.DatePart() 函数来实现,参考如下代码: var byWeek = data.GroupBy ...

最新文章

  1. 企业 SOA 设计(1)–ESB 设计
  2. java线程学习之notify方法和notifyAll方法
  3. 系统优化怎么做-Tomcat优化
  4. Java黑皮书课后题第11章:11.1(Triangle类)设计一个名为Triangle的类来继承GeometricObject类。该类包括:
  5. java使用教程——组件及事件处理——常用组件与布局
  6. 收集整理的较为经典的shell脚本合计
  7. 报错处理——# Creating Server TCP listening socket *:6379: bind: Address already in use
  8. 主数据文件损坏(或丢失)情况下,如何备份尾部事务日志.
  9. Jquery之append()和html()的区别
  10. 4. 使用Keras-神经网络来进行MNIST手写数字分类
  11. Java的安装以及配置
  12. android 斜线 绘制_Android绘图:绘制直线的 drawLine方法
  13. java小学生加减法_用java代码写随机加法算术题。 这些知识你不一定知道
  14. AT89C51单片机共阳极数码管动态显示(汇编语言)
  15. 如何屏蔽迅雷9右侧广告首页
  16. 带通滤波器c5000汇编语言,基于SIW技术的高选择性带通滤波器的设计与实现
  17. 【TypeScript】TS与Vue
  18. C# Speech学习笔记(一)
  19. 【已解决】win10离线安装.net framework 3.5(错误:0x8024402c)
  20. Eclipse插件安装(在线和离线方式)

热门文章

  1. 深度学习交通标志识别项目
  2. 防疫宣传二维码有哪些优势?
  3. 关于队里面最菜的在博客打卡第三十一天这件事
  4. PlatoFarm链上数据优异,最真实的元宇宙
  5. Magical String
  6. flutter app 换马甲
  7. CSGO(KZ模式)服务器搭建教程(windows系统)包含申请全球服务器操作方法
  8. 视频倒放怎么制作?视频倒放方法分享。
  9. 思科路由器:网络故障诊断与排除命令
  10. c语言整型变量程序基本,C语言的数据类型→整型数据