我的通用存储库中有一个返回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;
}
}
if语句的原因是大多数但不是所有表都有OrganisationID
,我想确保用户只能看到他们所属组织的数据。上面的代码有效,但为了使其工作,我必须添加AsEnumerable()
以将数据拉入内存。没有它,我收到错误消息
“无法将类型'Models.xxx'强制转换为类型 'Models.OrganisationDependent'。 LINQ to Entities仅支持强制转换 EDM原语或枚举类型“
我的所有实体都直接继承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; }
}
有没有办法可以克服这个限制,这样当类型是OrganisationDependent
的子类时,我会在OrganisationID
上过滤而不必将查询拉入内存?
答案 0 :(得分:4)
最简单的选择可能是使用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;
}
}