【问题标题】:Is it possible to create an extension method that can be used in an sql query?是否可以创建可用于 sql 查询的扩展方法?
【发布时间】:2019-12-07 00:00:27
【问题描述】:

我有一个应用程序,它在单击搜索按钮时从数据库中提取元素。我需要更新它,以便可以在字符串中找到具有特定 Substring 的元素,正好有 6 个位置。例如,我需要通过在第 6 位和第 7 位查找 33 来找到 111-2233-44-555。我的第一直觉是为字符串类创建一个扩展方法,这样我就可以这样说:

Dim example As String = "111-2233-44-555"
If example.HasYear(33) Then
  'Do Something'
End If

这很完美。这是我做的方法:

Public Module StringExtensionMethods
    ''' <summary>
    ''' Finds the year in a competition number of format XXX-XXXX-XX-XXX
    ''' </summary>
    ''' <param name="pstrCompNum">The competition number to find the year in</param>
    <Extension()>
    Public Function HasYear(ByVal pstrCompNum As String, ByVal pstrCompYear As String) As Boolean
        Try

            Dim testString As String = pstrCompNum

            Debug.Print(testString)
            Dim testSubstring As String = testString.Substring(6, 2)
            If testSubstring.Equals(pstrCompYear) Then
                Return True
            End If
            Return False

        Catch ex As Exception
            Throw ex
        End Try
    End Function
End Module

但是当我尝试在SQL 查询中使用此方法时出现问题。没错,因为HasYear()SQL 没有任何关系。这是我要执行的查询:

Dim o = From c In myContext.Competitions.Include("CodeJusticeBranches").Include("CodeJusticeLocations").Include("CodeCompetitionTypes").Include("CodePositionTypes").Include("CompetitionPositions") _
                        Where (pstrCompNum Is Nothing OrElse c.comp_number = pstrCompNum) _
                        And (pstrCompYear Is Nothing OrElse c.comp_number.HasYear(strYear) = True) _
                        And (pstrCompTypeId Is Nothing OrElse c.CodeCompetitionTypes.code_ct_id = CInt(pstrCompTypeId)) _
                        And (pstrBranchId Is Nothing OrElse c.CodeJusticeBranches.code_branch_id = CInt(pstrBranchId)) _
                        And (pstrPosTypeId Is Nothing OrElse c.CodePositionTypes.code_pos_type_id = CInt(pstrPosTypeId)) _
                        Order By c.comp_number _
                        Select c

我收到错误 LINQ to Entities 无法识别方法 'Boolean HasYear (System.String, System.String)' 方法,并且此方法无法转换为存储表达式。

所以我正在寻找的本质上是一种制作可用于SQL 查询的扩展方法的方法。有什么想法吗?

【问题讨论】:

  • 许多框架方法在 LINQ 中不起作用,因为 SQL 服务器不支持它们。您应该只包含查询中支持的方法,然后输入ToList() 来执行查询,然后使用您不支持的方法过滤结果数据。
  • SubString 应该可以翻译成 SQL,所以你根本不能使用 HasYear 函数。
  • 好主意,我试过了,效果很好。谢谢。

标签: sql vb.net visual-studio


【解决方案1】:

不要在 LINQ 中包含自定义函数。它必须可以转换为 SQL,因此您的扩展方法不符合条件。只需使用支持的 where 子句执行您的查询,然后在之后添加您的自定义查询。

Dim o = (
    From c In myContext.Competitions.Include("CodeJusticeBranches").Include("CodeJusticeLocations").Include("CodeCompetitionTypes").Include("CodePositionTypes").Include("CompetitionPositions")
    Where (pstrCompNum Is Nothing OrElse c.comp_number = pstrCompNum) _
    And (pstrCompTypeId Is Nothing OrElse c.CodeCompetitionTypes.code_ct_id = CInt(pstrCompTypeId)) _
    And (pstrBranchId Is Nothing OrElse c.CodeJusticeBranches.code_branch_id = CInt(pstrBranchId)) _
    And (pstrPosTypeId Is Nothing OrElse c.CodePositionTypes.code_pos_type_id = CInt(pstrPosTypeId))
    Order By c.comp_number Select c).ToList().
    Where(Function(c) c.pstrCompYear Is Nothing OrElse c.comp_number.HasYear(strYear))

【讨论】:

  • 我喜欢这个,但我看到了@Andrew Morton 写的内容,我决定继续这样做。在我的主管眼中,它最终也成为了更好的解决方案。感谢您的回答,但是,欢迎我了解不同解决方案的任何知识(我是初学者程序员),我绝对会在以后的某个地方找到它的用途。
  • @BrenCou 在这种情况下,也许Substring 有效。但是在某些情况下,您的函数更复杂并且您不能/不想将其转换为 SQL。然后我的方法有效。如果性能不会受到太大影响,您可能希望使用您的函数来提高可读性/可理解性,因为HasYear 的意图比Substring(6, 2) = ... 更明显。
  • 我同意可读性部分。 HasYear 更直观,但是我们已经为 Substring 的使用创建了一些很好的文档,所以我认为我们应该很好。另外,当我说我将能够找到它的用途时,这就是我的意思。不知道我需要解决什么问题,而您的解决方案一定会派上用场。
【解决方案2】:

我喜欢 @djv 发布的内容,但我决定尝试 Andrew Morton 的建议,完全省略 HasYear()。我最终使用了这个:

Dim k = From c In myContext.Competitions.Include("CodeJusticeBranches").Include("CodeJusticeLocations").Include("CodeCompetitionTypes").Include("CodePositionTypes").Include("CompetitionPositions") _
                        Where (pstrCompNum Is Nothing OrElse c.comp_number = pstrCompNum) _
                        And (pstrCompYear Is Nothing OrElse c.comp_number.Substring(6, 2) = pstrCompYear) _
                        And (pstrCompTypeId Is Nothing OrElse c.CodeCompetitionTypes.code_ct_id = CInt(pstrCompTypeId)) _
                        And (pstrBranchId Is Nothing OrElse c.CodeJusticeBranches.code_branch_id = CInt(pstrBranchId)) _
                        And (pstrPosTypeId Is Nothing OrElse c.CodePositionTypes.code_pos_type_id = CInt(pstrPosTypeId)) _
                        Order By c.comp_number _
                        Select c

注意And (pstrCompYear Is Nothing OrElse c.comp_number.Substring(6, 2) = pstrCompYear)这一行

这很简单地解决了我的问题。

【讨论】:

    猜你喜欢
    • 2015-06-11
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    相关资源
    最近更新 更多