C# 正在尝试编写通用筛选器IQueryable

C# 正在尝试编写通用筛选器IQueryable,c#,asp.net-mvc,generics,iqueryable,C#,Asp.net Mvc,Generics,Iqueryable,我正在尝试编写一个通用过滤器。 我的数据库中几乎每个表都使用这个过滤器。我需要一个通用的Equals过滤器,这样我就可以应用到我的所有表,而无需到处重复我的代码 :我有以下代码: public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source, FilterDTO filterModel) { var type = typeof(T); if(filterMo

我正在尝试编写一个通用过滤器。 我的数据库中几乎每个表都使用这个过滤器。我需要一个通用的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;
}
我得到这个错误:

我做错了什么

如果
iCompanyId==filterModel.SelectedCompanyId

这是我如何调用过滤器的:

telematicDevices.ApplyFilterModel(model.FilterDTO);

如果远程通信设备是DB(实体框架)中的IQueryable,您不能应用.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);
}
公共静态IQueryable ApplyFilterModel(此IQueryable源,FilterTo filterModel)
:其中T:i公司特定
{
返回source.Where(o=>o.iCompanyId==filterModel.SelectedCompanyId);
}

您不能应用.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);
}
公共静态IQueryable ApplyFilterModel(此IQueryable源,FilterTo filterModel)
:其中T:i公司特定
{
返回source.Where(o=>o.iCompanyId==filterModel.SelectedCompanyId);
}

您可以尝试以下方法:

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;
public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source,
    FilterDTO filterModel)
{
    return Queryable.Equals<T, int>(source, p => p.iCompanyId);
}
公共静态IQueryable ApplyFilterModel(此IQueryable源,FilterTo filterModel)
{
var类型=类型(T);
如果(filterModel.SelectedCompanyId!=0)
{
var parameterExp=Expression.Parameter(类型,“type”);
var propertyExp=Expression.Property(参数exp,“iCompanyId”);
var constExp=Expression.Constant(filterModel.SelectedCompanyId,typeof(int));//我假设SelectedCompanyId是一个int。
var equalExp=表达式.Equal(propertyExp,constExp);
var lambda=表达式.lambda(equalxp,constExp);
source=source.Provider.Where(lambda);
}
返回源;

}

您可以尝试以下方法:

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;
public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source,
    FilterDTO filterModel)
{
    return Queryable.Equals<T, int>(source, p => p.iCompanyId);
}
公共静态IQueryable ApplyFilterModel(此IQueryable源,FilterTo filterModel)
{
var类型=类型(T);
如果(filterModel.SelectedCompanyId!=0)
{
var parameterExp=Expression.Parameter(类型,“type”);
var propertyExp=Expression.Property(参数exp,“iCompanyId”);
var constExp=Expression.Constant(filterModel.SelectedCompanyId,typeof(int));//我假设SelectedCompanyId是一个int。
var equalExp=表达式.Equal(propertyExp,constExp);
var lambda=表达式.lambda(equalxp,constExp);
source=source.Provider.Where(lambda);
}
返回源;

}

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

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;
public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source,
    FilterDTO filterModel)
{
    return Queryable.Equals<T, int>(source, p => p.iCompanyId);
}
公共静态IQueryable ApplyFilterModel(此IQueryable源,
过滤器到过滤器模型)
{
返回Queryable.Equals(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);
}
公共静态IQueryable ApplyFilterModel(此IQueryable源,
过滤器到过滤器模型)
{
返回可查询的。其中(源、,
p=>p.iCompanyId==filterModel.SelectedCompanyId);
}
  • 您需要让lambda实际比较必须与
    filterModel.SelectedCompanyId
    进行比较的属性。这意味着使用
    Expression.Equals
    传递投影属性和表示要与之比较的值的常量
  • 表达式使用
    Where
    而不是
    Equals
    。Call
    Call。(或者,就此而言,只调用
    Where
    作为方法,而不是构建表示该调用的表达式,因为它将通过实现将自身表示为表达式。)

  • 这是假设你不想让你的生活变得简单,这不仅简单得多,而且还允许静态输入。

    你正在创建的表达式,如果是静态写出来的,看起来像这样:

    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;
    
    public static IQueryable<T> ApplyFilterModel<T>(this IQueryable<T> source,
        FilterDTO filterModel)
    {
        return Queryable.Equals<T, int>(source, p => p.iCompanyId);
    }
    
    公共静态IQueryable ApplyFilterModel(此IQueryable源,
    过滤器到过滤器模型)
    {
    返回Queryable.Equals(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);
    }
    
    公共静态IQueryable ApplyFilterModel(此IQueryable源,
    过滤器到过滤器模型)
    {
    返回可查询的。其中(源、,
    p=>p.iCompanyId==filterModel.SelectedCompanyId);
    }
    
  • 您需要让lambda实际比较必须与
    filterModel.SelectedCompanyId
    进行比较的属性。这意味着使用
    Expression.Equals
    传递投影属性和表示要与之比较的值的常量
  • 表达式使用
    Where
    而不是
    Equals
    。Call
    Call。(或者,就此而言,只调用
    Where
    作为方法,而不是构建表示该调用的表达式,因为它将通过实现将自身表示为表达式。)

  • 这是假设你不想让你的生活变得简单,这不仅简单得多,而且还允许静态输入。

    如何?我的数据库中几乎每个表都使用这个过滤器。我需要一个通用的Equals过滤器,这样我就可以应用到我所有的表,而无需重复我的代码。在这里,我为你的基类添加了一个带有通用约束的代码示例。但我不知道,可能是汽车、人或员工。如果我使用:where T:People我不能将其用于CarsIs是否存在包含iCompanyId的基类或接口?@psibernetic使用
    partial
    类将允许他添加到生成的类中(例如,通过添加要实现的接口),而不会在重新生成类型时将其删除。如何?这