【问题标题】:Is there a better way to do this LINQ statement block?有没有更好的方法来执行此 LINQ 语句块?
【发布时间】:2009-08-13 22:33:02
【问题描述】:

我对 LINQ 还比较陌生,但我会更深入地了解它。以下是 LINQ 的实际应用,还是有更好的方法来做这样的事情?

Public Shared Function GetItems(ByVal itemsList As List(Of OrderItem), 
 ByVal whichForm As ItemsFor, ByVal formID As Integer) As List(Of OrderItem)
    Dim items As New List(Of OrderItem)
    Select Case whichForm
        Case ItemsFor.MfrCredit
            Dim query = From oi As OrderItem In itemsList _
Where oi.ManufacturerCreditID = formID Select oi
            items = query
        Case ItemsFor.CustomerCredit
            Dim query = From oi As OrderItem In itemsList _
 Where oi.CustomerCreditID = formID Select oi
            items = query
        Case ItemsFor.Invoice
            Dim query = From oi As OrderItem In itemsList _
 Where oi.InvoiceID = formID Select oi
            items = query
        Case ItemsFor.PurchaseOrder
            Dim query = From oi As OrderItem In itemsList _
 Where oi.PurchaseOrderID = formID Select oi
            items = query
        Case ItemsFor.Quote
            Dim query = From oi As OrderItem In itemsList _
 Where oi.QuoteID = formID Select oi
            items = query
        Case ItemsFor.StockingOrder
            Dim query = From oi As OrderItem In itemsList _
 Where oi.StockingOrderID = formID Select oi
            items = query
    End Select
    Return items
End Function

我在想如果我能以某种方式获取属性名称作为一个对象,我可以只做一个 LINQ 语句,但我不确定具体如何......

谢谢!

【问题讨论】:

    标签: asp.net vb.net linq refactoring


    【解决方案1】:

    你可以这样做:

    Dim condition As Func(Of OrderItem, Boolean)
    Select Case whichForm
        Case ItemsFor.MfrCredit
            condition = Function(oi As OrderItem) oi.ManufacturerCreditID = formID
        Case ItemsFor.CustomerCredit
            condition = Function(oi as OrderItem) oi.CustomerCreditID = formID
        ...
    End Select
    Return items.Where(condition).ToList()
    

    它并不完美,但至少它的代码重复更少......

    【讨论】:

    • 我喜欢这个...这看起来很简单
    【解决方案2】:

    您可以使用Predicate 委托。我正在想象一个谓词数组或列表,每个 ItemsFor 一个。

    那么你的查询是

    Dim query = From oi As OrderItem In itemsList Where predicate select oi 
    

    另见this article on building predicates
    还有this article on PredicateBuilder

    【讨论】:

      【解决方案3】:

      您可以使用 LINQ 表达式,如下所示:(我的 VB 已生锈,因此可能无法编译)

      Dim param = Expression.Parameter(GetType(OrderItem), "item")
      Dim getter = Expression.Lambda(Of Func(Of OrderItem, Integer))( _
          Expression.Property(param, whichForm.ToString()), _
          param _
      ).Compile()
      
      Return items.Where(Function(item) getter(item) == formId)
      

      为获得最佳性能,请将生成的委托缓存在 Dictionary(Of ItemsFor, Func(Of OrderItem, Integer)) 中。

      编辑

      System.Linq.Expressions 命名空间允许您在运行时创建函数。此 coe 使用该功能创建一个获取属性的函数。由于Compile 方法(实际上是创建函数)有点慢,所以最好重用每个生成的委托。

      【讨论】:

      • 不过,这是最短的方法。
      【解决方案4】:

      您可以将其转换为单个查询的一种方法是:

      Dim query = From oi As OrderItem In itemsList _
      Where ((whichForm = ItemsFor.MfrCredit) and (oi.ManufacturerCreditID = formID)) _
      or ((whichForm = ItemsFor.CustomerCredit) and (oi.CustomerCreditID = formID)) _
      or ((whichForm = ItemsFor.Invoice) and (oi.InvoiceID = formID)) _
      ...
      select oi
      items = query
      

      【讨论】:

        【解决方案5】:

        有一个很好的article here 在使用 VB 的 Linq 中通过手动创建表达式树进行动态搜索...相当多的工作。或者另一个(更好的?)选项是Dynamic Linq 上的这篇文章(这里的例子是 C#)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多