【问题标题】:LINQ expression to expression tree via API in VB通过 VB 中的 API 将 LINQ 表达式转为表达式树
【发布时间】:2013-04-09 06:56:26
【问题描述】:

我有一个相对简单的 LINQ 表达式,我需要将其转换为 VB 表达式树语法。对于熟悉的人来说,这可能是一件容易的事,但我是 LINQ 表达式树领域的新手。

在我的示例中,您会看到一个“New Int16() {}”数组。该值必须在运行时使用来自另一个代码元素的值数组进行参数化。

我的查询是:

from i in tblInstitutions
let ChildHasCategory = i.tblInstCtgyHistories.Where(Function(CtgyHist) CtgyHist.EndDate is Nothing AND ( (New Int16() {32,35,38,34}).Contains(CtgyHist.InstCtgyCodeFK)))
where ChildHasCategory.Any()
select i

也可以表示为:

tblInstitutions
.Select (i => new  {
        i = i, 
        ChildHasCategory = (IEnumerable<tblInstCtgyHistory>)(i.tblInstCtgyHistories)
           .Where (
              CtgyHist => 
                    ((CtgyHist.EndDate == null) & 
                       (IEnumerable<Int16>)(new Int16[] { 32, 35, 38, 34 } ).Contains (CtgyHist.InstCtgyCodeFK)
                    )
           )
     }
)
.Where ($VB$It => $VB$It.ChildHasCategory.Any ())
.Select ($VB$It => $VB$It.i)

这将在 ASP.NET 动态数据 Web 应用程序中的自定义过滤器上下文中使用。我想模仿默认方法。 其他动态过滤器代码隐藏示例之一是:

Public Overrides Function GetQueryable(source As IQueryable) As IQueryable
    Dim value = TextBox1.Text
    If String.IsNullOrWhiteSpace(value) Then
        Return source
    End If

    If DefaultValues IsNot Nothing Then
        DefaultValues(Column.Name) = value
    End If

    Dim parameter = Expression.Parameter(source.ElementType)
    Dim columnProperty = Expression.PropertyOrField(parameter, Column.Name)
    Dim likeValue = Expression.Constant(value, GetType(String))
    Dim condition = Expression.Call(columnProperty, GetType(String).GetMethod("Contains"), likeValue)
    Dim where = Expression.Call(GetType(Queryable), "Where", New Type() {source.ElementType}, source.Expression, Expression.Lambda(condition, parameter))
    Return source.Provider.CreateQuery(where)
End Function

【问题讨论】:

  • 查询可以简化为:from i in tblInstitutions where (i.tblInstCtgyHistories.Where(Function(CtgyHist) CtgyHist.EndDate is Nothing AND ((New Int16() {32,35,38,34 }).Contains(CtgyHist.InstCtgyCodeFK)))).Any() 选择 i

标签: vb.net linq api linq-to-sql lambda


【解决方案1】:

我不确定您是否真的需要在这里担心表达式树。首先,我们应该能够如下表达您的查询:

Dim targetCodes = new Int16() {32, 35, 38, 34 } ' This could be data driven as well
return from i in tblInstitutions
       where i.tblInstCtgyHistories.Any(Function(ctgyHist) ctgyHist.EndDate is Nothing AndAlso 
              targetCodes.Contains(ctgyHist.InstCtgyCodeFK))
       select i

鉴于此,在什么情况下需要自定义表达式树?

【讨论】:

  • 正确,查询可以这样表达。但是,我需要将其转换为可用作动态数据应用程序自定义过滤器的 GetQueryable 函数的一部分的格式。它使用表达式调用和 API 语法方法,因为过滤器需要与动态数据应用程序的所有其他选定过滤器混合。我似乎无法确定 Expression.Call 和 Expression.Parameter 方法的正确组合来完成我所需要的。我敢肯定,当它完成后可能只有 4 或 5 行代码,但这是一个巨大的障碍。
  • 只要您仍在可查询中工作,您应该能够使用和扩展表达式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多