具有泛型和接口的实体框架可重用过滤器

时间:2017-09-20 14:39:16

标签: asp.net-mvc linq linq-to-sql entity-framework-6 linq-to-entities

我正在尝试编写可重用的过滤查询以用于报告目的。目前的标准是

  1. 用户应该能够根据日期进行过滤
  2. 用户可以按用户信息过滤报告
  3. 为此,我有这样的事情:

    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是计算属性,实体框架将无法使用它。

    为了解决这个问题,我尝试了DelegateDecompilerMicrosoft.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。

0 个答案:

没有答案