【问题标题】:Trying to write a Generic Filter IQueryable尝试编写通用过滤器 IQueryable
【发布时间】:2015-04-18 16:39:37
【问题描述】:

我正在尝试编写一个通用过滤器。 这个过滤器几乎用于我的数据库中的每个表。我需要一个通用的 Equals 过滤器,这样我就可以应用到我的所有表中,而无需到处重复我的代码

:我有以下代码:

public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source, FilterDTO filterModel)
{
    var type = typeof(T);

    if(filterModel.SelectedCompanyId != 0)
    {
        var property = type.GetProperty("iCompanyId");
        var parameter = Expression.Parameter(type, "p");
        var propertyAccess = Expression.MakeMemberAccess(parameter, property);
        var orderByExp = Expression.Lambda(propertyAccess, parameter);
        var resultExp = Expression.Call(typeof(Queryable), "Equals", new[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
        source = source.Provider.CreateQuery<T>(resultExp);
    }

    return source;
}

type.GetProperty("iCompanyId"); iCompanyId 将始终是 Int32

所以当我调试并到达这一行时:

var resultExp = Expression.Call(typeof(Queryable), "Equals", new[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));

我收到此错误:

我在这里做错了什么?

如果iCompanyId == filterModel.SelectedCompanyId,我需要过滤Input IQueryable

这就是我调用过滤器的方式:

telematicDevices.ApplyFilterModel(model.FilterDTO);

telematicDevices 是数据库中的 IQueryable(实体框架)

【问题讨论】:

    标签: c# asp.net-mvc generics iqueryable


    【解决方案1】:

    你不能应用 .Where 语句吗?

    //Interface we need to access property
    public interface ICompanySpecific
    {
        public int iCompanyId { get; }
    }
    

    为每个具有 iCompanyId 的对象创建一个分部类来指定接口。

    public partial class Person : ICompanySpecific
    {
        //No code is needed because Person already has the iCompanyId property
    }
    

    现在您可以将它与 Person 或任何实现 ICompanySpecific 的类型一起使用

    public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source, FilterDTO filterModel)
        : where T: ICompanySpecific
    {
        return source.Where(o => o.iCompanyId == filterModel.SelectedCompanyId);
    }
    

    【讨论】:

    • 怎么样?这个过滤器几乎用于我的数据库中的每个表。我需要一个通用的 Equals 过滤器,这样我就可以应用于我的所有表,而无需在任何地方重复我的代码
    • 我为您的基类添加了一个带有通用约束的代码示例。
    • 但我不知道 ,它可能是汽车、人、员工任何东西。如果我使用 : where T: People 我不能将它用于汽车
    • 是否有包含 iCompanyId 的基类或接口?
    • @psib​​ernetic 使用partial 类将允许他添加到生成的类(例如,通过添加要实现的接口),而不会在重新生成类型时删除它.
    【解决方案2】:

    你总是可以尝试这样的:

    public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source, FilterDTO filterModel)
    {
    var type = typeof(T);
    
    if(filterModel.SelectedCompanyId != 0)
    {
        var parameterExp = Expression.Parameter(type, "type");
        var propertyExp = Expression.Property(parameterExp, "iCompanyId");
        var constExp = Expression.Constant(filterModel.SelectedCompanyId, typeof(int)); // I'm assuming that SelectedCompanyId is an int.
        var equalExp = Expression.Equal(propertyExp, constExp);
        var lambda = Expression.Lambda<Func<T, bool>>(equalExp, constExp);
        source = source.Provider.Where(lambda);
    }
    
    return source;
    

    }

    【讨论】:

      【解决方案3】:

      您正在创建的表达式,如果以静态方式写出,将如下所示:

      public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source,
          FilterDTO filterModel)
      {
          return Queryable.Equals<T, int>(source, p => p.iCompanyId);
      }
      

      你真正想做的是创建这个的动态版本:

      public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source,
          FilterDTO filterModel)
      {
          return Queryable.Where<T, int>(source, 
              p => p.iCompanyId == filterModel.SelectedCompanyId);
      }
      
      1. 您需要让您的 lambda 实际将您拥有的属性与 filterModel.SelectedCompanyId 进行比较。这意味着使用 Expression.Equals 传入投影属性和表示要与之比较的值的常量。
      2. 使用Where 而不是Equals 调用Expression.Call。 (或者,就此而言,只是将 Where 作为方法调用,而不是构建表示该调用的表达式,因为它将通过其实现将自己表示为表达式。)

      这是假设你不想让你的生活变得轻松而只是 write out the implementation statically 这不仅更容易,而且还允许静态类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-05
        • 1970-01-01
        • 1970-01-01
        • 2021-01-04
        • 1970-01-01
        • 2017-10-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多