[英]How to conditionally filter IQueryable by type using generic repository pattern
I have a method in my generic repository that returns an IQueryable<T>
: 我的通用存储库中有一个返回IQueryable<T>
:
public virtual IQueryable<T> All
{
get
{
DbSet<T> set = Context.Set<T>();
if (typeof(T).IsSubclassOf(typeof(OrganisationDependent)))
return set.AsEnumerable()
.Cast<OrganisationDependent>()
.Where(x => x.OrganisationID == CurrentOrganisationID)
.AsQueryable()
.Cast<T>();
return set;
}
}
The reason for the if statement is that most, but not all of my tables have an OrganisationID
and I want to ensure that a user only sees data for the organisation they belong to. if语句的原因是大多数但不是所有表都有一个OrganisationID
,我想确保用户只能看到他们所属组织的数据。 The above code works but in order to make it work I had to add the AsEnumerable()
to pull the data into memory. 上面的代码工作,但为了使它工作,我不得不添加AsEnumerable()
将数据拉入内存。 Without it I get the error message 没有它,我收到错误消息
"Unable to cast the type 'Models.xxx' to type 'Models.OrganisationDependent'. LINQ to Entities only supports casting EDM primitive or enumeration types" “无法将类型'Models.xxx'转换为'Models.OrganisationDependent'类型.LINQ to Entities仅支持转换EDM原语或枚举类型”
All my entities directly inherit either ModelBase
or OrganisationDependent
: 我的所有实体都直接继承ModelBase
或OrganisationDependent
:
public abstract class OrganisationDependent : ModelBase
{
public int OrganisationID { get; set; }
public virtual Organisation Organisation { get; set; }
}
public abstract class ModelBase
{
public int ID { get; set; }
}
Is there a way that I can overcome this restriction so that when the type is a sub class of OrganisationDependent
, I filter on OrganisationID
without having to pull the query into memory? 有没有办法可以克服这个限制,以便当类型是OrganisationDependent
的子类时,我过滤OrganisationID
而不必将查询拉入内存?
The simplest option is probably to use the LINQ Expressions API to build a filter expression dynamically: 最简单的选择可能是使用LINQ Expressions API动态构建过滤器表达式:
private static readonly PropertyInfo _organizationIdProperty
= typeof(OrganisationDependent).GetProperty("OrganisationID");
private static Expression<Func<T, bool>> FilterByOrganization<T>(int organizationId)
{
var item = Expression.Parameter(typeof(T), "item");
var propertyValue = Expression.Property(item, _organizationIdProperty);
var body = Expression.Equal(propertyValue, Expression.Constant(organizationId));
return Expression.Lambda<Func<T, bool>>(body, item);
}
public virtual IQueryable<T> All
{
get
{
IQueryable<T> set = Context.Set<T>();
if (typeof(T).IsSubclassOf(typeof(OrganisationDependent)))
{
var filter = FilterByOrganization<T>(CurrentOrganisationID);
set = set.Where(filter);
}
return set;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.