为实体框架制作全局过滤器 [英] making a global filter for entity framework
问题描述
对于我的模型,我所有的都有一个活动的
属性,如果模型没有显示在管理上,我想过滤所有不活动
什么是最好的方法,我正在使用的是以下
For my models I have a active
attribute on all of them, and i want to filter all inactive if the model was not displayed on the administration
What is the best way to do that, What I'm currently using is the following
在我的基础模型类中,我有这种方法来过滤集合
in my base model class i have this method that filters the collections
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;
}
在我的模型中,对于每个关系我都做了以下方法
and on my model for every relation i did the following method
DbSet<T> set ...
var X = set.Where(some filter);
var list = globalDefaultScope(X).ToList();
return list;
现在我有一些严重的问题,当我想要加载一些子关系使用 include(Xmodel.Ymodel)
我在 get
globalDefaultScope >方法,用于过滤集合的集合,但如果集合中的某些项目处于非活动状态,则该方法会不断引发此异常。
And now I'm having some serious problems when i want to eagerly load some subrelations using include("Xmodel.Ymodel")
i called the globalDefaultScope
in the get
method for that collection that filters the collection but it keeps throwing this exception when some items in the collection are inactive
系统。 InvalidOperationException:
操作失败:无法更改关系,因为一个或多个
的外键属性不可为空。
System.InvalidOperationException: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable.
我如何解决这个问题,或者我如何使这个过滤器更优雅的方式,因为我真的不太满意我如何实现它。
how can i fix this or how can i make this filter in a more elegant way because i'm really not very satisfied of how i implemented it.
请要求任何遗漏的信息或代码块或任何细节
please ask for Any missing information or code blocks or any details
更新:
我还发现这个 link ,但是这种方式并不适用于热切加载的条目( include()
)
I also found this link, but this way didn't work with eagerly loaded entries (include()
)
Update2:
这是我如何使用包含和发生错误的地方的示例
this is an example of how i use the include and where the error occurs
在我的模型
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;
}
虽然我无法过滤关系包括我做了以下:
while i couldn't filter the relations in the include i did the following :
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()抛出了提到的错误。
while we filter the results in sub_relation1, when i do db.SaveChanges() the mentioned error is thrown.
推荐答案
您可以创建扩展方法,如
You can create extension methods like
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);
这应该工作,请让我知道,如果你需要更多的信息。
This should work, Please Let me know if you need more information.
注意:请为System.Linq.Dynamic添加Nuget软件包以具有动态Linq库
更新1:
我已经在Webpages_Roles和UsreProfile中添加了IsActive,简单的成员资格表,还包括一个表,其中指向webpages_Roles的角色优先级,使用我将所有的关系改变成一对多(从许多到许多)。现在如果我使用类似于你的代码,当有没有角色的任何用户时,扩展方法会出错。
I have included IsActive in webpages_Roles and UsreProfile table of simple membership and also included one more table Role Priority which refers to webpages_Roles, for easy to use I have changed the all the relation ships to one to many(from many to many). now if I use code similar to yours, extension method gives error when there is any user for which there are no roles.
如果我给每个用户赋予角色,每个角色的优先级,这不会给出错误。
If I give roles to every user and I have priority for every roles then this won't give error.
请让我知道,如果你还需要任何其他信息。
Please Let me know if you still need any other info.
更新2
您可以创建一个扩展名方法,如
You can create one extension Method like
public static IQueryable<T> WhereActive<T>(this IQueryable<T> source)
{
return source.Where("isActive == true"); // From System.linq.Dynamic Library
}
并调用其他方法,如
and call other methods like
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);
请让我知道,如果您还需要任何其他信息。
Please Let me know if you still need any other info.
这篇关于为实体框架制作全局过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!