我正在尝试编写可重用的过滤查询以用于报告目的。目前的标准是
为此,我有这样的事情:
public class ReportQueryProvider<TCriteria, TModel> : IReportQueryProvider<TCriteria, TModel>
where TModel : class, IReportable<TModel>
where TCriteria : ReportCriteria
{
public Expression<Func<TModel, bool>> Filter(TCriteria criteria)
{
var a = PredicateBuilder.New<TModel>();
if (criteria.StartDateObject!=null)
a = a.And(x => x.date >= criteria.StartDateObject);
if (criteria.EndDateObject != null)
a = a.And(x => x.date <= criteria.EndDateObject);
var userFilter = QueryExtensions.UserCommonFilter(criteria);
a = a.And(m => userFilter.Invoke(m.FilterUser));
return a;
}
}
它适用于date
过滤器,因为每个模型/表都有date
字段/属性,但每个表的用户关联可以不同。这就是我用属性FilterUser
创建接口的原因,每个表都必须实现它并返回/映射其实际的User属性。
现在,由于FilterUser
是计算属性,实体框架将无法使用它。
为了解决这个问题,我尝试了DelegateDecompiler
和Microsoft.Linq.Translations
,但当我尝试通过上面的过滤器方法使用它们时,这两个似乎都不起作用使用泛型和接口。在DelegateDecompiler
的情况下,我得到错误,没有设置对象引用。对于Linq.Translations,它的行为就好像从未使用过翻译或不存在。
但是,如果我尝试在Generics之外(非Generics)方式使用它们,它们按预期工作,我可以使用EF FilterUser
属性。如果我将条件从IReportable<TModel>
更改为实现此接口的具体Model类之一,它们甚至可以工作。
我的样本模型类:
public partial class Dis_UserTransactions : IReportable<Dis_UserTransactions>
{
private static readonly CompiledExpression<Dis_UserTransactions, User> filterUserExpression
= DefaultTranslationOf<Dis_UserTransactions>.Property(e => e.FilterUser).Is(e => e.User1);
static Dis_UserTransactions()
{
}
[NotMapped]
public User FilterUser => filterUserExpression.Evaluate(this);
}
是否可以使其有效?
P.S。我已经在使用LinqKit。