从存储过程获取查询结果

时间:2018-07-19 13:06:18

标签: sql sql-server vb.net linq stored-procedures

我正在VB.Net中开发一个程序,该程序使用LINQ与数据库连接。现在,我正在尝试从数据库中的以下存储过程中获取数据:

CREATE PROCEDURE dbo.GetTableColumn(
    @ColName VARCHAR(MAX),
    @TblName VARCHAR(MAX),
    @Result  BIT OUT
) AS
BEGIN
    IF (EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TblName AND COLUMN_NAME = @ColName))
        BEGIN
            DECLARE @SQL VARCHAR(MAX)
            SET @SQL = 'SELECT ' + @ColName + ' FROM ' + @TblName
            EXEC (@SQL)
            SET @Result = 1
        END
    ELSE
        SET @RESULT = 0
    RETURN @Result
END

该过程的目标是,我可以发送一个列名和一个表名作为变量,如果该列存在于表中,则返回表中的数据。

我已将过程添加到DataLinqContext中,这是引用该过程的代码:

Public Function GetTableColumn(ByVal col As String, ByVal table As String) As AutoCompleteStringCollection
    GetTableColumn = New AutoCompleteStringCollection
    Using dbContext As New Customer_LINQDataContext
        Dim result As Boolean
        Dim query = dbContext.GetTableColumn(col, table, result)
        MessageBox.Show(query.ToString())
    End Using
End Function

现在,我进入“消息框”对话框来测试输出数据。但是,每次运行该方法时,结果始终为10。我永远无法获得要查询的实际数据。

那么我在这里做错了什么,如何解决?

编辑:我在Database Admin Stack Exchange上问过,看看那里是否有人可以提供任何帮助。我得到了以下希望对您有帮助的答案,但我仍然不确定如何解决该问题。

  

您的代码正在存储过程的末尾获取RETURN @result的结果。所需的结果作为ResultSet从存储过程中传递出去。您需要使用DataReader对象来查看行。

     

我不确定如何使用Linq做到这一点。希望您会在StackOverflow问题上得到更好的答案。

2 个答案:

答案 0 :(得分:0)

当sp在执行时没有错误时,通常使用存储过程返回代码0 ...为了获取记录集,如果sp没有找到表/列,我将使第3个参数无效并返回1:

CREATE PROCEDURE dbo.GetTableColumn(
    @ColName VARCHAR(MAX),
    @TblName VARCHAR(MAX)
) AS
BEGIN
    IF (EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TblName AND COLUMN_NAME = @ColName))
        BEGIN
            DECLARE @SQL VARCHAR(MAX)
            SET @SQL = 'SELECT ' + @ColName + ' FROM ' + @TblName
            EXEC (@SQL)
        END
    ELSE
        RETURN 1
END

在您的代码中...只需使用:

Dim query = dbContext.GetTableColumn(col, table)

答案 1 :(得分:0)

因此,要获得我想要的东西,我基本上必须停止使用Linq,因为我找不到任何使它工作的方法。我对该程序进行了一些修改,现在看起来像这样:

CREATE PROCEDURE dbo.GetTableColumn(
    @ColName VARCHAR(25),
    @TblName VARCHAR(25)
) AS
BEGIN
    IF (EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TblName AND COLUMN_NAME = @Col_Name))
        BEGIN
            DECLARE @SQL VARCHAR(MAX)
            SET @SQL = 'SELECT ' + @ColName + ' FROM ' + @TblName + ' WHERE ' + @ColName + ' IS NOT NULL'
            EXEC (@SQL)
        END
    ELSE
        RETURN 1
END

在那之后,我在VB.Net程序中添加了以下方法:

Public Function ExecuteCMD(ByRef CMD As SqlCommand) As DataSet
    Dim DS As New DataSet()
    Try
        OpenDBConnection() 'Custom class to open the DB Connection'
        CMD.Connection = DB_CONNECTION 'Private member set to db connection on initialization'

        If CMD.CommandText.Contains(" ") Then
            CMD.CommandType = CommandType.Text
        Else
            CMD.CommandType = CommandType.StoredProcedure
        End If

        Dim adapter as New SqlDataAdapter(CMD)
        adapter.SelectCommand.CommandTimeout = 300

        adapter.Fill(DS)
        CloseDBConnection 'Custom class to close DB Connection'
    Catch ex As Exception
        Throw New Exception("Database Error: " & ex.Message)
    End Try
    Return DS
End Function

此方法归功于Brian Webster here。大量的代码对使它起作用很有帮助。最后,我修改了GetTableColumn方法,使其看起来像这样:

Public Function GetTableColumn(ByVal col As String, ByVal table As String) As AutoCompleteStringCollection
    GetTableColumn = New AutoCompleteStringCollection
    Dim CMD As New SqlCommand("GetTableColumn")
    CMD.Parameters.Add("@ColName", SqlDbType.VarChar).Value = col
    CMD.Parameters.Add("@TblName", SqlDbType.VarChar).Value = table
    Dim DS As DataSet = ExecuteCMD(CMD)
    For Each DR As DataRow In DS.Tables(0).Rows
        If Not IsNothing(DR(0)) Then GetTableColumn.Add(CStr(DR(0)))
    Next
End Function

此设置可为我提供所需的结果,并且不会像LINQ那样使我痛苦不已,因此,如果其他人遇到与我相同的问题,我会在此发布此信息。如果沟渠LINQ开始令人沮丧,那是不值得的。

相关问题