【问题标题】:Store all queries inside a module?将所有查询存储在一个模块中?
【发布时间】:2013-06-06 08:48:38
【问题描述】:

我有一个关于 VBNET 的快速问题,我目前正在使用 VS 2012 Express 和 Microsoft Access 作为我的数据库。

我的问题是,我如何将查询放入模块而不是将查询放入表单本身? 假设我在 frmStock 中有这个功能:

frmStock:

Public Sub FillCategory(ByVal Key As String, ByVal Txt As String, ByVal N As TreeNode)
    Dim TD As TreeNode

    If N Is Nothing Then
        TD = tvCategory.Nodes.Add(Key, Txt)
    Else
        TD = N.Nodes.Add(Key, Txt)
    End If

    Dim cmd As New OleDbCommand("SELECT * FROM Category WHERE Category_Parent = ?", conn)
    cmd.Parameters.AddWithValue("Category_Parent", Key)

    Dim dr = cmd.ExecuteReader
    Do While dr.Read()
        FillCategory(dr("Category_ID"), dr("Category_Name"), TD)
    Loop
    dr.Close()
    cmd.Dispose()
End Sub

我想搬家

Dim cmd As New OleDbCommand("SELECT * FROM Category WHERE Category_Parent = ?", conn)

改为模块。

我试过了:

Module queryCollection

    Public getCategoryParent As New OleDbCommand( _
            "SELECT * FROM Category WHERE Category_Parent = ?", conn)

End Module

并将我的 FillCategory 函数修改为:

Public Sub FillCategory(ByVal Key As String, ByVal Txt As String, ByVal N As TreeNode)
    Dim TD As TreeNode

    If N Is Nothing Then
        TD = tvCategory.Nodes.Add(Key, Txt)
    Else
        TD = N.Nodes.Add(Key, Txt)
    End If

    getCategoryParent.Parameters.AddWithValue("Category_Parent", Key)

    Dim dr = getCategoryParent.ExecuteReader

    Do While dr.Read()
        FillCategory(dr("Category_ID"), dr("Category_Name"), TD)
    Loop
    dr.Close()
    getCategoryParent.Dispose()
End Sub

更新:
我的问题的一些屏幕截图:

我的数据库: http://puu.sh/39CMV.PNG

在将我的查询移入模块之前: http://puu.sh/39D0M.PNG

将我的查询移入模块后: puu.sh/39CVV.PNG

似乎只执行一次(?)为什么会这样?在模块中声明我的查询的正确方法是什么?

我实际上有大量查询,我想将它们存储到一个地方以便更有条理的编码。

【问题讨论】:

  • 你真的需要存储查询吗?你不能改用 LINQ to SQL 或 LINQ to EF 之类的东西吗?这比在代码中使用字符串文字查询要好得多。
  • @DoctorJones ,您好,感谢您的回复,我还没有遇到过 LINQ,我正在使用 Microsoft Access 作为我的数据库。我想将所有查询存储到一个模块中,主要是因为我的编码中有太多查询,看起来很乱,我需要组织它。
  • 我强烈建议您查看 LINQ to SQL。它消除了代码中的所有字符串文字查询,并将它们替换为强类型查询。这意味着您将在编译时而不是运行时发现拼写错误等,并使您的代码更易于维护。
  • @DoctorJones,非常感谢您提供的信息,稍后我将研究 LINQ 以进行优化:)

标签: sql database vb.net visual-studio-2012


【解决方案1】:

在您修改后的FillCategory 代码中,您调用了以下代码,但从未保存结果:

getCategoryParent.Parameters.AddWithValue("Category_Parent", Key)

这创建了一个OleDbCommand 对象,但随后它立即被丢弃。然后你打电话:

Dim dr = getCategoryParent.ExecuteReader

这会创建第二个 OleDbCommand 对象,但没有参数值。

修改你的代码:

Dim cmd = getCategoryParent.Parameters.AddWithValue("Category_Parent", Key)
Dim dr = cmd.ExecuteReader

编辑:以下将解决这两个问题。

Dim cmd = getCategoryParent
cmd.Parameters.AddWithValue("Category_Parent", Key)
Dim dr = cmd.ExecuteReader

以前 cmd 变量被 VB 修改为 InferOleDbParameter 对象,它没有 ExecuteReader 方法。之所以这样推断,是因为它是使用内联完成的 .Parameters.AddWithValue("Category_Parent", Key) 代码调用的方式。

通过此更改,cmd 被正确设置为OleDbCommand 变量,现在您可以根据需要多次使用AddParameter 方法。

编辑 2: getCategoryParent 当前被定义为模块的属性。这意味着getCategoryParent 方法在模块第一次实例化时执行一次,而不是每个循环执行一次。将该方法更改为函数,现在代码将在每个循环中执行一次,并且您的 TreeView 将按预期加载。

Public Function getCategoryParent() As OleDbCommand
    Return New OleDbCommand("SELECT * FROM Category WHERE Category_Parent = ?", conn)
End Function

【讨论】:

  • 您好,感谢您指出我的错误。但是我刚刚尝试修改了我的代码,它给了我一个错误: Dim dr = cmd.ExecuteRead //'ExecuteReader' is not a member of 'System.Data.Oledb.OleDbParameter' 另外另一个快速问题,如果我有多个参数要传入,如何传递?谢谢。
  • 你好,我试过你的代码,它现在可以工作了 :) 但是当我运行代码时,它似乎只执行一次,我将提供 SS 以获取更多详细信息:我的数据库:Database我的代码如何无需移出查询即可工作:No Error 移出查询后我的代码如何工作:Error 我如何调用 FillCategory() 函数:FillCategory("1", "All Categories", Nothing) 谢谢。
  • 对不起,如果我的评论让您感到困惑,Stackoverflow 不允许在评论中换行 :(
  • @MiloJuakMuTou - 查看我的编辑以了解为什么查询只执行一次。
  • 谢谢!!!这绝对是我今天要寻找的。非常感谢您的回答,尤其是附有解释! :) 再次感谢!
【解决方案2】:

我在 ASP.NET 和 Access 中采用的一种方法是将我的 SQL 作为文件保存到一个文件夹中,然后使用可能的单例加载它,如下所示:

Public Class FileHandler

    Public Shared Function LoadToString(ByVal pName As String) As String
        Dim rV As String
        Dim fio As StreamReader = File.OpenText(pName)
        rV = fio.ReadToEnd()
        fio.Close()
        Return rV
    End Function

End Class

然后从您的代码中调用它...

...
dim sqlStr As String = FileHandler.LoadToString("sql/mySqlStatement.sql")
...

不过,这很可能不是最佳解决方案。这样做的主要优点是您可以即时修改 SQL,而无需重新编译您的应用程序。

另一种方法是将 SQL 语句作为名称值对存储在 web.config 中,但同样,这不是一个很好的解决方案。

除非有人对此有更好的建议,否则我认为这将是最好的选择!

【讨论】:

  • 您好,感谢您的回复,我认为将查询存储在文本文件中不是一个好主意,如果我愿意,这可能最终会创建很多文件,20 个查询?
  • 只有 20 个?您可以在应用启动时加载所需的内容。
【解决方案3】:

把你的 SQL 字符串放在你的模块上怎么样..

Module queryCollection

    Public sCatParent As String = "SELECT * FROM Category WHERE Category_Parent = ?"

End Module 

你这样称呼它..

getCategoryParent As New OleDbCommand(sCatParent,conn)

getCategoryParent.Parameters.AddWithValue("Category_Parent", Key)

Dim dr = getCategoryParent.ExecuteReader

【讨论】:

  • 你好,这工作完美!但是我仍然期待更有效的代码,我也想知道为什么我的代码只执行一次。无论如何,非常感谢:D 如果没有更好的答案,我会使用它
猜你喜欢
  • 2011-01-13
  • 1970-01-01
  • 2017-05-08
  • 2021-04-28
  • 2019-05-10
  • 1970-01-01
  • 2019-12-03
  • 2015-10-01
相关资源
最近更新 更多