【问题标题】:Return a message from a stored procedure to C# app将消息从存储过程返回到 C# 应用程序
【发布时间】:2016-03-12 14:29:27
【问题描述】:

我有一个添加用户的存储过程,并且在我添加的每个权限处,我都想开始构建成功消息。

我的存储过程运行良好,但如何将成功消息返回到我的应用程序的消息对话框中?

我想在我的 C# 应用程序的消息框中显示以下 @text。

DECLARE @text NVARCHAR(1000)
SET @text = 'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.'
SELECT @text

这是我在 C# 应用程序中的调用:

    public DataTable CreateOrDropUser(string dataBase, string procedure, SqlParameter[] parameters)
    {
       try
       {
          if (dataBase.Length > 0) { procedure = dataBase + ".." + procedure; } //Set procedure to DBNAME..ProcedureName

          SqlCommand cmd1 = new SqlCommand(procedure, con);
          cmd1.CommandType = CommandType.StoredProcedure;

          foreach (SqlParameter p in parameters)
          {
              if (p != null)
              {
                  cmd1.Parameters.Add(p);
              }
          }

          con.Open();
          DataTable dt = new DataTable();
          SqlDataAdapter da = new SqlDataAdapter(cmd1);
          da.Fill(dt);
          con.Close();

          MessageBox.Show("Success"); //This should display the @text variable in my proc

          return dt;      
     }
     catch (Exception ex)
     {
        try
        {
           if (con.State == ConnectionState.Open)
           {
              con.Close();
           }
        }
        catch
        {
           MessageBox.Show("Could not connect to database. Check settings. " + ex.Message, "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        MessageBox.Show(ex.Message);
        return null;
      }      
    }

我的存储过程,只关注所有打印的部分,这就是我要添加的文本:

ALTER PROCEDURE [dbo].[AdminDevUserCreate]
    @SQLLoginName varchar(50),
    @SQLLoginPass varchar(50) 
AS


DECLARE @text NVARCHAR(1000)OUTPUT  

--PRINT 'Create SQL Login'
SET @text = 'Create SQL Login ' + @SQLLoginName 
-- USE [Master]

EXEC(' USE [master] CREATE LOGIN [' + @SQLLoginName + '] WITH PASSWORD=''' + @SQLLoginPass + ''', DEFAULT_DATABASE=[TestAudit], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF')

--PRINT 'Add Server Roles'
SET @text += + CHAR(13)+CHAR(10) + 'Add Server Roles'
--Add Server roles
    EXEC master..sp_addsrvrolemember @loginame = @SQLLoginName, @rolename = N'bulkadmin'
    EXEC master..sp_addsrvrolemember @loginame = @SQLLoginName, @rolename = N'processadmin'
    EXEC master..sp_addsrvrolemember @loginame = @SQLLoginName, @rolename = N'securityadmin'   
--PRINT 'Allow SQL Agent Job Manage'
SET @text += + CHAR(13)+CHAR(10) + 'Allow SQL Agent Job Manage'
--USE [MSDB]
EXEC ('msdb..sp_addrolemember ''SQLAgentOperatorRole'', ''' + @SQLLoginName + '''')

--PRINT 'Allow Trace'
SET @text += + CHAR(13)+CHAR(10) + 'Allow Trace'
--Allow trace (SQL Profiler)
--USE [MASTER]
EXEC (' USE [MASTER] GRANT ALTER TRACE TO ' + @SQLLoginName )

--PRINT 'Prevent admin proc changes '
SET @text += + CHAR(13)+CHAR(10) + 'Prevent admin proc changes '
    EXEC ('USE [TestAudit] DENY ALTER ON [TestAudit].[dbo].[Admin] TO ' + @SQLLoginName) --Prevents changes to Admin function
--PRINT 'Prevent database trigger changes'
SET @text += + CHAR(13)+CHAR(10) + 'Prevent database trigger changes'
    EXEC ('USE [TestAudit] DENY ALTER ANY DATABASE DDL TRIGGER TO ' + @SQLLoginName) --Prevents modify of [SchemaAuditTrigger]

PRINT @text
Select @text

【问题讨论】:

  • 试试MessageBox.Show(dt.Rows[0][0].ToString());

标签: c# sql-server


【解决方案1】:

最好的办法是使用输出参数。

在您的存储过程中添加参数@text nvarchar(1000) OUTPUT,然后在您的代码中添加一个名为@text 的额外参数,并将参数方向设置为output

然后只需在存储过程中添加行SET @text = 'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.'

编辑:我的回答是,如果您不希望这影响您当前的查询,如果我误解了您的问题,请告诉我。同样要获取值,在执行查询后,您可以使用 .Value 从@name 参数中获取值

编辑 2:示例代码应该类似于

//Add these lines
SqlParameter text = new SqlParameter("@name", SqlDbType.NVarChar);
text.Direction = ParameterDirection.Output;
cmd1.Parameters.Add(text);

con.Open();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd1);
da.Fill(dt);
con.Close();

//Change this line
MessageBox.Show(text.Value); //This should display the @text variable in my proc

如果您需要有关存储过程的帮助,请发布它,我也会给出一个示例

编辑 3:快速示例 使用快速示例进行测试。 C#代码:

        using (SqlConnection connection = new SqlConnection(@"Data Source=.\SQLExpress;Initial Catalog=TestDB;Integrated Security=True"))
        {
            connection.Open();
            using (SqlCommand command = connection.CreateCommand())
            {
                command.CommandType = CommandType.StoredProcedure;
                command.CommandText = "Test";

                SqlParameter text = new SqlParameter("@Text", SqlDbType.NVarChar, 1000);
                text.Direction = ParameterDirection.Output;
                command.Parameters.Add(text);

                using (DataTable dt = new DataTable())
                {
                    using (SqlDataAdapter da = new SqlDataAdapter(command))
                    {
                        da.Fill(dt);
                    }
                }

                Trace.WriteLine(text.Value);

                connection.Close();
            }
        }

存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE Test
    @Text Nvarchar(1000) OUTPUT
AS
BEGIN
    SET NOCOUNT ON;

    SET @Text = 'test'
END
GO

如果你想对照你的检查差异,对我来说工作得很好

编辑 4: 在您的存储过程中,@text 需要是一个参数,所以不是

ALTER PROCEDURE [dbo].[AdminDevUserCreate]
    @SQLLoginName varchar(50),
    @SQLLoginPass varchar(50) 
AS

DECLARE @text NVARCHAR(1000)OUTPUT  

做起来

ALTER PROCEDURE [dbo].[AdminDevUserCreate]
    @SQLLoginName varchar(50),
    @SQLLoginPass varchar(50),
    @text NVARCHAR(1000) OUTPUT 
AS

在创建 SqlParameter 时也使用

SqlParameter text = new SqlParameter("@Text", SqlDbType.NVarChar, 1000);

当你告诉它参数是NVARCHAR(1000)时,它应该消除大小问题

一行

PRINT @text
Select @text

不需要

【讨论】:

  • 我如何将该参数添加到输出?我添加了@text nvarchar(1000) OUTPUT,现在如何让我的消息框显示它?
  • @Pommy 不记得它是否与 SqlAdapters 不同,但我认为发布的代码应该可以工作,如果没有,请告诉我
  • 我收到此消息,对象引用未设置为对象的实例。
  • @Pommy 另外,您应该考虑使用语句包装您的 SqlConnection、SqlCommand、DataTable、SqlDataAdapter 等以防止内存泄漏(请参阅msdn.microsoft.com/en-us/library/yh598w02.aspx
  • 我添加消息框如下 MessageBox.Show("Success" + text.Value);我的信息就是成功。
【解决方案2】:

可以从SqlConnection.InfoMessage 事件中检索信息消息。它们可以在 T-SQL 代码中使用 RAISERROR 引发,严重性为 0-9。

 public DataTable CreateOrDropUser(string dataBase, string procedure, SqlParameter[] parameters)
    {
        SqlconnecitonStringBuilder scsb = new SqlConnectionStringBuilder (connstring);
        scsb.Database = database;
        using (SqlConnection con = new SqlConnection (scsb.ConnectionString))
        {
            StringBuilder sb = new StringBuilder ();
            con.Open ();

            SqlCommand cmd1 = new SqlCommand(procedure, con);
            cmd1.CommandType = CommandType.StoredProcedure;
            foreach (SqlParameter p in parameters)
            {
                if (p != null)
                {
                    cmd1.Parameters.Add(p);
                }
            }

            conn.InfoMessage += (args => 
            {
              sb.AppendLine (args.Message);
            });
            DataTable dt = new DataTable();
            SqlDataAdapter da = new SqlDataAdapter(cmd1);
            da.Fill(dt);
            MessageBox.Show(sb);
            return dt;      
        }
    }

在 T-SQL 中:

RAISERROR(N'This is line %d', 0,0,1);
RAISERROR(N'This is line %d', 0,0,2);

【讨论】:

    【解决方案3】:

    如果您使用的是 MVC,那么有一个很好的示例 here。我在多个项目中使用过它,发现它很棒。

    另外,你真的应该将 SqlCommandSqlConnection 对象包装在 using 语句中以阻止泄漏连接。

    注意:这可以适应WebForms而不用太麻烦。

    【讨论】:

      【解决方案4】:
      MessageBox.Show(dt.Rows[0][0].Tostring());
      

      使用输出参数

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-21
        • 1970-01-01
        • 2020-05-01
        • 1970-01-01
        • 2011-11-03
        • 1970-01-01
        • 2020-07-14
        • 1970-01-01
        相关资源
        最近更新 更多