从SQL存储过程返回值

时间:2014-12-12 18:41:39

标签: sql-server vb.net tableadapter

我在Microsoft SQL Server数据库中有一个存储过程:

USE [ProjectIndexer]
GO
/****** Object:  StoredProcedure [files].[add_file]    Script Date: 12/12/2014 1:34:20 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON 
GO
ALTER PROCEDURE [files].[add_file]
    @FILENAME varchar(255),
    @EXTENSION nvarchar(8),
    @PATH_FULL varchar(255), 
    @RELATIVE_PATH varchar(255), 
    @JOB varchar(15), 
    @DATE_MODIFIED datetimeoffset(7), 
    @SIZE BIGINT, 
    @INDEX_MODULE INT, 
    @FILE_TYPE varchar(255), 
    @DOC_TYPE varchar(255), 
    @DISCIPLINE varchar(255)
AS
    DECLARE @file_id sql_variant

    --Insert values for new file 
    INSERT INTO files.GENERAL 
        (FILENAME, EXTENSION, PATH_FULL, RELATIVE_PATH, JOB, DATE_MODIFIED, SIZE, INDEX_MODULE, FILE_TYPE, DOC_TYPE, DISCIPLINE) 
        VALUES(@FILENAME, @EXTENSION, @PATH_FULL, @RELATIVE_PATH, @JOB, @DATE_MODIFIED, @SIZE, @INDEX_MODULE, @FILE_TYPE, @DOC_TYPE, @DISCIPLINE);

    --Get the ID of this new file
    SELECT @file_id = current_value FROM sys.sequences WHERE name = 'FILE_ID_SEQ';

--Return ID
RETURN CONVERT(bigint, @file_id)

我正在尝试使用表适配器在Visual Studio 2012中开发的VB应用程序中运行此过程:

Dim myFilesGeneralTableAdapter As New FILES_GeneralTableAdapter
Dim FileID As Int32

FileID = myFilesGeneralTableAdapter.AddFile(FileName, fileExtension, foundFile, fileRelativePath, JobNumber, fileDateModified, fileSize, Nothing, Nothing, Nothing, Nothing)

由于某种原因,该函数没有将值返回给VB变量'FileID'。但是,我可以使用数据集设计器中的“预览数据”功能在Visual Studio中插入上述参数的值,在该环境中我可以获得返回值。

这告诉我,我的VB模块中的语法是错误的。谁能告诉我错误是什么?

3 个答案:

答案 0 :(得分:0)

您是否考虑过使用System.Data.SqlClient.SqlCommand?您可以使用它来调用存储过程,添加参数值,并以检索单个值的方式执行它,即

Try
    'Create command'
    Dim command As New SqlCommand
    command.CommandType = CommandType.StoredProcedure
    conn = New SqlConnection(myConnString)
    command.Connection = conn
    command.CommandText = "add_file"

    command.Parameters.AddWithValue("@Filename", [Filename])
    ...
    command.Parameters.AddWithValue("@Discipline", Discipline)

    command.Connection.Open()
    Dim i As Int64 = command.ExecuteScalar()
    command.Connection.Close()

    'returns record ID'
    Return i

Catch ex As Exception
    Throw ex
Finally
    If conn.State <> ConnectionState.Closed Then
        conn.Close()
    End If
End Try

请注意,在此示例中,“myConnString”是一个String,其值为我正在连接的数据库的连接字符串。

答案 1 :(得分:0)

我采用了将脚本转换为Entity Framework模型的好建议。起初,存储过程没有返回我想要的东西(它只返回1的整数值),但是我在网上发现了一个资源,指示我创建一个&#34;函数导入&#34;在EF模型中。执行此操作并正确匹配变量类型后,我设法让存储过程在Visual Studio中返回正确的值。这是一个很好的资源:

http://www.devtoolshed.com/using-stored-procedures-entity-framework-scalar-return-values

答案 2 :(得分:0)

在从TableAdapter转换为实体框架之外(无论如何都是一个好的举动),您可以更好地返回OUTPUT参数或结果集中的值。存储过程返回值实际上是为了传达操作的状态代码,因此非常有限。

此外,通过在INSERT之后执行以下操作(即作为单独的步骤),

--Get the ID of this new file
SELECT @file_id = current_value FROM sys.sequences WHERE name = 'FILE_ID_SEQ';

如果某个其他进程几乎同时插入该表(即在此特定INSERT和此特定SELECT之间),则您可能会冒错误值。

考虑到上述两个问题,在INSERT语句中使用OUTPUT子句会相当简单,而且非常可靠:

--Insert values for new file
INSERT INTO files.GENERAL
    (FILENAME, EXTENSION, PATH_FULL, RELATIVE_PATH, JOB, DATE_MODIFIED, SIZE,
     INDEX_MODULE, FILE_TYPE, DOC_TYPE, DISCIPLINE)
  OUTPUT INSERTED.FILE_ID
  VALUES(@FILENAME, @EXTENSION, @PATH_FULL, @RELATIVE_PATH, @JOB, @DATE_MODIFIED,
         @SIZE, @INDEX_MODULE, @FILE_TYPE, @DOC_TYPE, @DISCIPLINE);

这将生成1行1列结果集。该列将被命名为FILE_ID或任何实际字段名称(我猜这是基于用于其他字段和变量的命名约定)。

然后摆脱DECLARE @file_idSELECT ...RETURN ...