【问题标题】:How to run SQL transactions using C# (Using TSql110Parser)如何使用 C# 运行 SQL 事务(使用 TSql110Parser)
【发布时间】:2018-05-03 07:54:13
【问题描述】:

我创建了一个 ASP.Net C# 应用程序来运行 SQL 服务器 (MSSQL) 查询。 应用程序读取提供的文本框中的所有用户输入查询,并使用 TSql110Parser,它将分解为单独的 SQL 语句。

它在几乎所有情况下都运行良好,除非 SQL 语句如下所示

    DECLARE @user VARCHAR(50)
    SET @user = 'ABC'
    PRINT @user
    SELECT * FROM user_table WHERE username = @user

执行在第 2 行停止,SQL Server 错误提示

必须声明标量变量“@user”

即使它在第一行中定义。

然后我想出了下面的运行方式。添加 BEGIN 和 END 语句。

    BEGIN
    DECLARE @user VARCHAR(50)
    SET @user = 'ABC'
    PRINT @user
    SELECT * FROM user_table WHERE username = @user
    END

但是,仍然存在一个限制,即我们将无法从 SELECT 查询返回结果。

下面是C#代码sn-p

    protected void btnQuery_Click(object sender, EventArgs e)
        {
            if (qry.Length > 0)
            {
                using (sqlCon = new SqlConnection())
                {
                    dbConnString = dbConnString + "database=" + ddlDBNames.SelectedValue + ";";
                    sqlCon.ConnectionString = dbConnString;
                    sqlCon.Open();              
                    cmd = new SqlCommand();
                    cmd.Connection = sqlCon;
                    IList<ParseError> Errors;
                    var parser = new TSql110Parser(false);
                    var script = parser.Parse(new StringReader(qry), out Errors) as TSqlScript;
                    if (Errors.Count > 0)
                    {
                        lblErrorMessage.Text = "***** Error: No statements executed *****";
                    }
                    else
                    {
                        foreach (var ts in script.Batches)
                        {
                            foreach (var st in ts.Statements)
                            {
                                q = qry.Substring(st.StartOffset, st.FragmentLength);
                                ExecStatement(st, q);
                            }
                        }
                    }

                }
            }

        }

    protected void ExecStatement(TSqlStatement statement, string qry)
        {
            cmd.CommandText = qry;
            if (statement is SelectStatement)
            {
                SqlDataReader dr = cmd.ExecuteReader(); 
                //code to populate the tabular result      
            }
            else
            {
                cmd.ExecuteNonQuery();
                //code to show the non query execution result
            }
        }

有没有什么可能的方法可以运行与数据库服务器的持久连接的 SQL 查询,以便第一行中的声明能够在查询中使用?

下面的应用截图。

【问题讨论】:

  • qry 的内容怎么样??
  • 与顶部给出的查询相同
  • 您需要 Exec() 批处理,而不是语句。
  • @devio 我需要分批显示每个语句的结果。用户将一次执行多个选择语句。此 Exec() 命令是否显示批处理中单个语句的结果?如果是,您能帮忙详细说明一下它的用法吗?
  • 这就是我的想法。首先在你的代码后面,如果语句是打印,“更改”它为选择语句,添加一个额外的列以便稍后识别它。将它们全部放在一个临时存储过程中(是的,您可以使用 c# 从 sql 接收多个数据集,但不能使用 ExecuteNonQuery)。有点棘手,但我认为它会起作用。

标签: c# sql asp.net sql-server tsql


【解决方案1】:

使用 CONTEXT_INFO。它是特定于连接的全局变量。

它的使用并不简单,因为它只是一个 128 位的值。要设置它,请运行以下代码(N = 要存储的 int 连接方式)

DECLARE @BinVar binary(128);
SET @BinVar = cast(N as binary(128));
set context_info @BinVar

您可以通过调用 context_info() 函数在后续查询中获取 N。你应该用这样的东西来转换它。

convert(int, context_info()) 

【讨论】:

  • 感谢您的评论。所需的操作不在 SQL 端。它在 C# 方面。我提到的查询只是一个示例。查询始终是动态的,因为这些查询将由多个用户提供。
  • 您可以在 C# 代码中打开连接,运行第一个查询。然后,使用相同的连接对象,运行其他查询并在其中调用 context_info()。或者至少,这就是我从“以便第一行中的声明能够在整个查询中使用?”的理解。 :)
  • TSQLParser 会自动将整个查询解析为多个 SQL 语句。因此,在第一个 SQL 查询中,解析器会将其识别为 4 个单独的 SQL 语句,而在第二个 SQL 查询中(使用 BEGIN 和 END),它将识别为单个语句。在 C# 中,我在“using (sqlCon = new SqlConnection())”语句中运行所有查询,所以理想情况下它应该使用同一组连接对象。
  • 已添加屏幕截图以便更好地理解
猜你喜欢
  • 2023-01-21
  • 1970-01-01
  • 2015-11-05
  • 2021-12-08
  • 2017-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多