9

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

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

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

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

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

include("Xmodel.Ymodel")现在,当我想急切地加载一些子关系时,我遇到了一些严重globalDefaultScopeget问题

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

我该如何解决这个问题,或者如何以更优雅的方式制作这个过滤器,因为我真的对我如何实现它不太满意。

请询问任何缺失的信息或代码块或任何细节

更新:

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

更新2:

这是我如何使用包含以及错误发生位置的示例

在我的模型中

public IQueryable<Dish> 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<SubRelation1> _sub_relation1 {get; set;}
public ICollection<SubRelation1> sub_relation1 {
get 
{
   //something like:
   return GlobalDefaultScope(_sub_relation1 ).ToList(); 
}  
set;}

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

4

2 回答 2

8

您可以创建扩展方法,例如

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

并像使用它们一样

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

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

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

更新1:

我在简单成员的webpages_Roles 和UsreProfile 表中包含了IsActive,并且还包括了一个引用webpages_Roles 的表Role Priority,为了便于使用,我将所有关系更改为一对多(从多到多)。现在,如果我使用与您类似的代码,当有任何没有角色的用户时,扩展方法会出错。

如果我为每个用户分配角色并且我对每个角色都有优先权,那么这不会出错。

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

更新 2

您可以创建一种扩展方法,例如

public static IQueryable<T> WhereActive<T>(this IQueryable<T> 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);

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

于 2013-09-12T13:58:40.263 回答
2

你可以这样做:

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

您可以在此答案中找到工作代码: How to soft delete using Entity Framework Code First

于 2013-10-17T22:12:03.093 回答