前言
在項目開發中,我們很多時候都會設計 軟刪除、所屬用戶 等等一系列字段 來方便我們在業務查詢的時候進行各種過濾
然后引申的問題就是:
在業務查詢的時候,我們要如何加上這些條件?或者動態禁用某些查詢條件呢?
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 }
這樣我們這邊就得到了一個標准
例如 我們我們需要一個 所屬用戶和 軟刪除 的數據篩選器 我們只需要繼承他即可
我們如何區分他們呢?
我們在之前使用 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 }
然后我們定義我們的 所屬用戶和 軟刪除 的數據篩選器 並為他們設置名稱
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 }
說明:
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 }
這樣 我們所有接口 和實現定義好了 如何管理呢?
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
說明:
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 }
"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 }
然后我們在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 }
初始化完成后如何將條件付給 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 }
在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 }
這樣我們的篩選器已經全部注入完成了
還剩下一個我們之前說的
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 }
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 }
這樣 我們可以傳入指定的篩選器名稱 啟用自己想要的
最終我們的倉儲就變成了這樣:
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 }
說明:倉儲的設計理念是從 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 }

