将消息从存储过程返回到 C# 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11260418/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 17:09:45  来源:igfitidea点击:

Return a message from a stored procedure to C# app

c#sql-server

提问by Pomster

I have a stored procedure that adds a user and at each permission I add, I want to start building a success message.

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

My stored procedure runs fine but how do I get that success message back into a message dialog in my app?

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

I want to display the below @text in a messagebox in my C# app.

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

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

This is my call in my C# app:

这是我在 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;
      }      
    }


My Stored proc, Just focus on sections by all the prints, that's the text i'm adding:

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

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

采纳答案by Manatherin

Your best bet is to use a output parameter.

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

In your stored procedure add the parameter @text nvarchar(1000) OUTPUTthen in your code add an extra parameter with the name @textand set the parameter direction to output.

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

then just add the line SET @text = 'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.'in your stored procedure

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

Edit:My answer is if you don't want this to affect your current query, if i misinterpreted your question please let me know. Also to get the value, after you execute the query you can get the value from the @nameparameter using .Value

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

Edit 2: Example CodeShould look something like

编辑 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

if you need help with the stored procedure please post it and i'll give a example with that too

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

Edit 3: Quick exampleTested with a quick example. The C# code:

编辑 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();
            }
        }

The Stored Procedure:

存储过程:

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

Worked fine for me if you want to check it against yours for differences

如果您想根据您的差异来检查它对我来说很好用

Edit 4:In your stored procedure the @text needs to be a parameter so instead of

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

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

DECLARE @text NVARCHAR(1000)OUTPUT  

make it

做了

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

also when creating the SqlParameter use

也在创建 SqlParameter 时使用

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

which should get rid of the size issue as you are telling it that the parameter is NVARCHAR(1000)

当您告诉它参数是 NVARCHAR(1000)

the line

线

PRINT @text
Select @text

shouldn't be needed

不应该需要

回答by Sudhakar B

Your data table dt has your text output. you can For eg

您的数据表 dt 有您的文本输出。你可以例如

MessageBox.Show("" + dt.Rows[0][0]);

回答by Kane

If you are using MVC then there is an excellent sample here. I have used it in multiple projects and found it fantastic.

如果您正在使用MVC则是一个很好的样本这里。我在多个项目中使用过它,发现它很棒。

Also you should really be wrapping your SqlCommandand SqlConnectionobject in using statements to stop leaky connections.

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

Note: this can be adapted to WebForms without too much trouble.

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

回答by Asif

MessageBox.Show(dt.Rows[0][0].Tostring());

or

或者

Use a output parameter

使用输出参数

回答by Remus Rusanu

Informational messages can be retrieved from SqlConnection.InfoMessageevent. They can be raised in T-SQL code using RAISERRORwith severity 0-9.

可以从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;      
        }
    }

And in T-SQL:

在 T-SQL 中:

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