【问题标题】:How build dynamic where clause with string argument如何使用字符串参数构建动态 where 子句
【发布时间】:2019-06-25 02:29:53
【问题描述】:

我尝试构建一种方法来将 where 子句添加到 Linq-to-SQL 请求(返回 IQueryable)。我尝试了几种方法,但总是使用 ToString、Indexof... 但这个结果是一个 sql 请求获取所有元素和 linq 中的过滤器。我在 SQL Server 探查器中看到了请求。 我想要一种方法来完成它,结果是一个包含 where 的 sql 请求

我在 Visual Studio 2017 和 SQL Server 2016 中工作。我在 vb.net 中编写代码

我在linq dynamic library 中看到了一件有趣的事情。但我无法适应我的情况

 <Extension()> _
    Public Function Where(ByVal source As IQueryable, ByVal predicate As String, ByVal ParamArray values() As Object) As IQueryable
        If source Is Nothing Then Throw New ArgumentNullException("source")
        If predicate Is Nothing Then Throw New ArgumentNullException("predicate")
        Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, GetType(Boolean), predicate, values)
        Return source.Provider.CreateQuery( _
            Expression.Call( _
                GetType(Queryable), "Where", _
                New Type() {source.ElementType}, _
                source.Expression, Expression.Quote(lambda)))
    End Function

但我不需要所有这些复杂的结构。这是几年我建立我的公用事业。但是需要升级。这是我的实用程序代码

<Extension()>
Public Function Where(ByVal source As IQueryable, ByVal predicate As String) As IQueryable
    Dim param = Expression.Parameter(GetType(String), "x")
    Return source.Provider.CreateQuery(
            Expression.Call(
                GetType(Queryable), "Where",
                New Type() {source.ElementType},
                source.Expression, Expression.Quote(Expression.Lambda(Expression.Constant(predicate), param))))
End Function


Public Function TFOAppliqueFiltreTri(Of T, MaClassDatas As Class)(Origins As IQueryable(Of T), ByVal MesDonnees As TableFullOption.PagerTabEnCours(Of MaClassDatas)) As IQueryable(of T)
    Dim retour As New TableFullOption.LstRetour

    'Colonne de filtre
    Dim strWh As String = ""
    Dim Filtredrecords As IQueryable(Of T)
    For Each Sort In MesDonnees.MesOptions
                       
                Dim colName = Sort.ColName
                If strWh.Length > 0 Then strWh = strWh & " AND "
                strWh = strWh & String.Format(colName & " like '%{0}%'", Sort.Search)
                           
    Next
    If strWh.Length > 0 Then
        Filtredrecords = Origins.Where(strWh) '<- Here call Where
    Else
        Filtredrecords = Origins
    End If

   
  
    Return Filtredrecords 
End Function

我收到此错误:

Aucune méthode générique 'Where' sur le type 'System.Linq.Queryable' n'est compatible avec les arguments de type et les argumentsfournis..

那么我的问题是正确编写 lambda 表达式。我的谓词参数是:Column1 like '%aaa%'。我想重写dynamicLinq的where方法以直接接受字符串参数:Column1 like '%aaa%'

感谢您的帮助

【问题讨论】:

  • 感谢您的回复。但就我而言,我不知道 colname。它是动态的。我从包含 ColName 的 MesDonnees.MesOptions 中提取它
  • LINQ to SQL 将Contains(x) 转换为like %x%,因此您可以只执行q.Where(r =&gt; r.field.Contains("aaa"))(固定到参考字段)。
  • 你能不能给个样品。我不明白。我有一个从 linq 到 sql 的 q 。在一个参数中,我有一个作为字符串的列并作为字符串搜索。如何访问 r.field.contains?
  • 我推荐 LINQPad 作为分析 Expression 树的优秀工具 - 您可以创建一个表示树的 lambda,然后 Dump 结果以查看编译器如何构建树(或者您可以使用 ExpressionVisitor Swap 方法并修改您的 lambda)。

标签: vb.net dynamic linq-to-sql


【解决方案1】:

终于在谷歌大量阅读和一些感觉之后,当然有很多机会。

 Public Function Where(Of TEntity)(source As IQueryable(Of TEntity), searchColumn As List(Of String), searchValue As String) As IQueryable(Of TEntity)
    Dim cond As Expression = Nothing
    Dim ParamExpr = Expression.Parameter(GetType(TEntity), "x")
    Dim conCat2 = GetType(String).GetMethod("Concat", New Type() {GetType(String), GetType(String)})
    Dim conCat4 = GetType(String).GetMethod("Concat", New Type() {GetType(String), GetType(String), GetType(String), GetType(String)})
    Dim Delim = Expression.Constant("/")
    Dim DateName = GetType(SqlFunctions).GetMethod("DateName", New Type() {GetType(String), GetType(Nullable(Of DateTime))})
    Dim DatePart = GetType(SqlFunctions).GetMethod("DatePart", New Type() {GetType(String), GetType(Nullable(Of DateTime))})
    Dim DblToString = GetType(SqlFunctions).GetMethod("StringConvert", New Type() {GetType(Nullable(Of Double))})

    For Each cn In searchColumn
        For Each colName In cn.Split("|")
            If Not colName.estVide Then
                Dim body As Expression = ParamExpr
                For Each member In colName.Split(".")
                    body = Expression.PropertyOrField(body, member)
                Next
                Dim Tostr As Expression
                If body.Type.FullName.Contains("String") Then
                    Tostr = body
                ElseIf body.Type.FullName.Contains("DateTime") Then
                    Dim day = Expression.Call(Expression.Call(conCat2, Expression.Constant("0"), Expression.Call(DateName, Expression.Constant("day"), body)), "Substring", Nothing, Expression.Constant(0), Expression.Constant(2))
                    Dim Month = Expression.Call(DatePart, Expression.Constant("MM"), body)
                    Dim toDouble = Expression.Convert(Month, GetType(Nullable(Of Double)))
                    Dim mois = Expression.Call(conCat2, Expression.Constant("0"), Expression.Call(Expression.Call(DblToString, toDouble), "Trim", Nothing))
                    Dim an = Expression.Call(DateName, Expression.Constant("year"), body)
                    Tostr = Expression.Call(conCat2, Expression.Call(conCat4, day, Delim, mois, Delim), an)
                Else
                    Tostr = Expression.Call(body, "Convert.ToString", Nothing)
                    'Tostr = Expression.Convert(body, GetType(String))
                End If
                Dim condPart = Expression.Call(Expression.Call(Tostr, "ToLower", Nothing), "Contains", Nothing, Expression.Call(Expression.Constant(searchValue), "ToLower", Nothing))
                If cond Is Nothing Then
                    cond = condPart
                Else
                    cond = Expression.OrElse(cond, condPart)
                End If
            End If
        Next
    Next
    Return source.Provider.CreateQuery(Of TEntity)(Expression.Call(GetType(Queryable), "Where", New Type() {GetType(TEntity)}, source.Expression, Expression.Lambda(cond, ParamExpr)))
End Function

现在我有一个动态过滤器,它生成一个带有完整子句的 SQL 请求,其中

【讨论】:

    猜你喜欢
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    相关资源
    最近更新 更多