EF Core 中實現 動態數據過濾器


 

前言

  在項目開發中,我們很多時候都會設計  軟刪除、所屬用戶 等等一系列字段 來方便我們在業務查詢的時候進行各種過濾

  然后引申的問題就是:

    在業務查詢的時候,我們要如何加上這些條件?或者動態禁用某些查詢條件呢?

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM