为entity framework制作全局filter

对于我的模型,我在所有模型上都有一个active属性,如果管理中没有显示模型,我想过滤所有非活动状态。最好的方法是什么,我目前使用的是以下内容

在我的基础模型类中,我有这个过滤集合的方法

 public virtual IQueryable GlobalDefaultScope(IQueryable c) where T : CModel { if (settings.is_admin) { c = c.Where(m => m.active); } return c; } 

在我的每个关系的模型上,我做了以下方法

 DbSet set ... var X = set.Where(some filter); var list = globalDefaultScope(X).ToList(); return list; 

现在我有一些严重的问题,当我想急切地使用include("Xmodel.Ymodel")加载一些子关系时,我在该集合的get方法中调用了globalDefaultScope来过滤集合,但它在某些项目时不断抛出此exception在集合中是不活动的

System.InvalidOperationException:操作失败:无法更改关系,因为一个或多个外键属性不可为空。

我怎么能解决这个问题,或者我怎么能以更优雅的方式制作这个filter,因为我真的不太满意我是如何实现它的。

请询问任何遗漏的信息或代码块或任何细节

更新:

我也找到了这个链接 ,但这种方式不适用于急切加载的条目( include()

UPDATE2:

这是我如何使用包含和错误发生的示例

在我的模型中

 public IQueryable getSomeRelation(bool eagerly_load_sub_relation1, bool eagerly_load_sub_relation2) { var query = getQuery(...); //getQuery => query = db.Entry(obj).Collection(collection).Query() //GlobalDefaultScope(query) if ( eagerly_load_sub_relation1){ query = query.Include(m => m.sub_relation1); } if (eagerly_load_sub_relation2){ query = query.Include("sub_relation2.sub_relation_of_sub_relation2"); } return query; } 

虽然我无法过滤包含中的关系我做了以下事情:

 private ICollection _sub_relation1 {get; set;} public ICollection sub_relation1 { get { //something like: return GlobalDefaultScope(_sub_relation1 ).ToList(); } set;} 

当我们在sub_relation1中过滤结果时,当我执行db.SaveChanges()时,会抛出上述错误。

您可以创建类似的扩展方法

 public static IQueryable Where(this IQueryable source, Expression> predicate) { source = source.Where("isActive == true"); // From System.linq.Dynamic Library source = Queryable.Where(source, predicate); return source; } 

并使用它们

 var user = db.UserProfiles.Include("webpages_Roles").Where(u => u.UserId < 30); 

这应该工作,如果您需要更多信息,请告诉我。

注意:请为System.Linq.Dynamic添加Nuget包以获得动态Linq库

更新1:

我已经将webAages_Roles和UsreProfile表中的IsActive包含在简单成员资格中,还包括一个表格Role Priority,它指的是webpages_Roles,为了便于使用我已经将所有关系变为一对多(从多对多)。 现在如果我使用类似于你的代码,当有任何没有角色的用户时,扩展方法会出错。

如果我给每个用户赋予角色,并且我对每个角色都有优先权,那么这不会给出错误。

如果您还需要任何其他信息,请告诉我。

更新2

您可以创建一个扩展方法

 public static IQueryable WhereActive(this IQueryable source) { return source.Where("isActive == true"); // From System.linq.Dynamic Library } 

并调用其他方法,如

 var user = db.UserProfiles.Include("webpages_Roles").WhereActive().Where(u => u.UserId < 30); 

要么

 var user = db.UserProfiles.Include("webpages_Roles").WhereActive().FirstOrDefault(u => u.UserId < 30); 

如果您还需要任何其他信息,请告诉我。

你可以这样做:

  1. 在OnModelCreating中,为每个可以被软删除的实体添加一个IsDeleted鉴别器
  2. 覆盖SaveChanges并查找要删除的所有条目
  3. 在这些条目上运行SQL以设置IsDeleted鉴别器,然后将其状态设置为“已分离”
  4. 更改任何唯一索引以忽略任何软删除的记录

您可以在此答案中找到工作代码: 如何使用Entity Framework Code First进行软删除