【问题标题】:Correct syntax to define an IQueryable<TSource>.OrderBy( ) like method正确定义 IQueryable<TSource>.OrderBy() 方法的语法
【发布时间】:2020-05-19 15:58:51
【问题描述】:

我需要创建一个扩展方法来检查我需要对数据库表查询进行的检查。对于模型中的不同表,我需要在 MVC 应用程序的所有控制器中进行检查。这就是为什么我想将代码集中在一个扩展方法中。

为了让你理解上下文,我将使用一个发明和简化的案例来解释。

假设我有两个名为 ATableBTable 的 Db 实体。两者都与Company 表有关系。

在正常情况下,我使用此代码按公司条件进行过滤:

var queryA = db.ATable.where(a => a.Company.IsEnabled)

var queryB = db.BTable.where(b => b.Company.IsEnabled)

条件比这更复杂,但通过这个简化的案例就很清楚了。

我的想法是这样称呼:

var queryA = db.ATable.CheckByCompany(a => a.Company);

var queryB = db.BTable.CheckByCompany(b => b.Company);

也就是说,仅使用相关属性调用方法,并且该方法将负责在该属性上创建整个条件。这种调用方式类似于OrderBy 扩展方法,所以我想我可以做类似的事情。

我的第一次尝试是创建一个名为ICompany 的接口,其中Company 作为唯一的属性,并在ATableBTable 类中实现它。这样我就创建了这个方法:

    public static IQueryable<TSource> CheckByCompany<TSource>(this IQueryable<TSource> source)
          where T: ICompany
    {
        if (source == null)
            throw new ArgumentNullException();

        IQueryable<TSource> query = source.Where(t => source.Company.IsEnabled);

        // The rest of the conditions I need for Company entity.

        return query;
    }

至少可以编译,但在运行时抛出异常,因为 Linq 无法识别 ICompany。

我的下一个尝试可能是创建一个类似于 OrderBy 扩展方法的方法,但我不知道定义它的正确语法。

我做了类似的事情:

public static IQueryable<TSource> CheckByCompany<TSource, Company>(this IQueryable<TSource> source, Expression<Func<TSource, Company>> company)

但是,在那之后,我该如何使用它?那个方法签名正确吗?

我看到了 OrderBy 扩展方法的源代码,但是不太容易理解。

有什么建议吗?

詹姆

【问题讨论】:

  • 我不太明白你想让你的CheckByCompany 做什么。如果我传入a =&gt; a.Company,它将变成Where(a =&gt; a.Company.IsEnabled) 调用。我可以在那里传递哪些其他 lambda 表达式?
  • 条件比这复杂得多。它也是根据网页中存在的一些变量动态构建的。模型中的所有表都与公司实体相关,并且在 MVC 应用程序的每个控制器中多次调用该条件。如果由于某种原因,该条件发生了变化,我将需要多次更改它,并有可能出错。如果是这样的话,在一处修改条件会更容易。
  • 你还没有回答我的问题?...听起来除了a =&gt; a.Company之外,您不会传递其他任何东西...那为什么还有参数呢?
  • 对不起,你是对的。我只会将a.Company 传递给扩展方法。

标签: c# linq lambda entity-framework-6 extension-methods


【解决方案1】:

我终于实现了本页中提到的解决方案:https://codingsight.com/using-expressions-to-filter-data-of-database/

我的最终扩展方法是这样的:

    public static IQueryable<TSource> FiltraEmpresaCliente<TSource>(this IQueryable<TSource> source, ParentController controller, Expression<Func<TSource, Empresa>> empresa)
    {
        if (source == null)
            throw new ArgumentNullException();

        if (empresa == null)
            throw new ArgumentNullException();

        Expression<Func<TSource, bool>> filterValidity = entity => empresa.Call()(entity).Cliente.ClienteEliminadoEn == null && empresa.Call()(entity).Cliente.ClienteVigente && empresa.Call()(entity).EmpresaEliminadoEn == null && empresa.Call()(entity).EmpresaVigente;
        Expression<Func<TSource, bool>> filterCustomer = null;
        Expression<Func<TSource, bool>> filterCompany = null;

        var empresaId = controller.EmpresaID;
        if (empresaId > 0)
            filterCompany = entity => empresa.Call()(entity).EmpresaId == empresaId;

        var clienteId = controller.ClienteID;
        if (clienteId > 0)
            filterCustomer = entity => empresa.Call()(entity).ClienteId == clienteId;

        IQueryable<TSource> query = source.Where(filterValidity.SubstituteMarker());

        if (filterCompany != null)
            query = query.Where(filterCompany.SubstituteMarker());

        if (filterCustomer != null)
            query = query.Where(filterCustomer.SubstituteMarker());

        return query;
    }

它有效,但是,我想知道性能如何。你有一些cmets吗?

问候 詹姆

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 2023-03-10
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多