【问题标题】:c# Building Dynamic SQL in c#c# 在 c# 中构建动态 SQL
【发布时间】:2020-01-26 22:10:00
【问题描述】:

尝试在我的 c# 代码中构建动态 SQL 字符串。不知道我哪里出错了。

private void Save_Item_Drop_Data()
{
    string uri = string.Empty;
    string strUpdate = string.Empty;
    WBGUpdateValue Update = new WBGUpdateValue();
    Update.Email = Game_Data._User_Account.Email;

    try
    {
        foreach (Base_Item item in Game_Data._Item_Drop)
        {
            //Recipe
            if (item.Name.Contains("Recipe"))
            {
                if (Update_Recipe(item.Name))
                {
                    uri = Game_Data._EndPoint + "api/WhiteboxGaming/Post_UnlockRecipe";
                    strUpdate = strUpdate + "UPDATE Skill_Gemology SET " + item.Name + "= 1 WHERE Email = ''" + Update.Email + "'' ";
                    _txtGameMessage.text = item.Name + " Unlocked";
                }
            }
            //Rune
            else if (item.Name.Contains("Rune") || item.Name == "Polished_Ancient_Stone" || item.Name == "Ancient_Stone")
            {
                uri = Game_Data._EndPoint + "api/WhiteboxGaming/Post_SaveItemdrop";
                strUpdate = strUpdate + "UPDATE Inventory_Runes SET " + item.Name + "=" + item.Name + " + " + item.Count.ToString() + " WHERE Email = ''" + Update.Email + "'' ";
                _txtGameMessage.text = "Found Rune";
            }

            Debug.Log(Update);
        }
    }
    catch (Exception ex)
    {
        Debug.Log(ex);
    }        

    if (Game_Data._Item_Drop.Count > 0)
    {
        Update.Value_1 = strUpdate;
        StartCoroutine(booleanwebrequest(uri, Update));            
    }
    Game_Data._Item_Drop = new List<Base_Item>();
}

字符串构建了这个:

UPDATE Inventory_Runes SET Polished_Ancient_Stone=Polished_Ancient_Stone + 1 WHERE Email = ''help.whiteboxgaming@gmail.com'' 

当我通过 SQL 运行它时,我得到一个错误:

消息 911,第 16 级,状态 4,第 74 行
数据库 'UPDATE Inventory_Runes SET Polished_Ancient_Stone=Polished_Ancient_Stone + 1 WHERE Email = 'help' 不存在。确保名称输入正确。

我了解它告诉我的内容,但我不确定如何修复我的 c# 代码中的电子邮件部分。

更新:现在我真的很困惑。我的动态 SQL 是正确的,但它仍然失败。

更新

//Rune
            else if (item.Name.Contains("Rune") || item.Name == "Polished_Ancient_Stone" || item.Name == "Ancient_Stone")
            {
                uri = Game_Data._EndPoint + "api/WhiteboxGaming/Post_SaveItemdrop";
                strUpdate = strUpdate + "UPDATE Inventory_Runes SET [" + item.Name + "] = [" + item.Name + "] + " + item.Count.ToString() + " WHERE Email = ''' + @Email + '''";
                _txtGameMessage.text = "Found Rune";
            }

输出:

'UPDATE Inventory_Runes SET [Polished_Ancient_Stone] = [Polished_Ancient_Stone] + 4 WHERE Email = ''' + @Email + '''UPDATE Inventory_Runes SET [Rune_sa] = [Rune_sa] + 1 WHERE Email = ''' + @Email + '''UPDATE Inventory_Runes SET [Polished_Ancient_Stone] = [Polished_Ancient_Stone] + 1 WHERE Email = ''' + @Email + '''UPDATE Inventory_Runes SET [Ancient_Stone] = [Ancient_Stone] + 2 WHERE Email = ''' + @Email + '''UPDATE Inventory_Runes SET [Ancient_Stone] = [Ancient_Stone] + 1 WHERE Email = ''' + @Email + ''''

当我把它撕开时,它看起来像这样:

UPDATE Inventory_Runes SET [Polished_Ancient_Stone] = [Polished_Ancient_Stone] + 4 WHERE Email = 'help.whiteboxgaming@gmail.com'
UPDATE Inventory_Runes SET [Rune_sa] = [Rune_sa] + 1 WHERE Email = 'help.whiteboxgaming@gmail.com'
UPDATE Inventory_Runes SET [Polished_Ancient_Stone] = [Polished_Ancient_Stone] + 1 WHERE Email = 'help.whiteboxgaming@gmail.com'
UPDATE Inventory_Runes SET [Ancient_Stone] = [Ancient_Stone] + 2 WHERE Email = 'help.whiteboxgaming@gmail.com'
UPDATE Inventory_Runes SET [Ancient_Stone] = [Ancient_Stone] + 1 WHERE Email = 'help.whiteboxgaming@gmail.com'

【问题讨论】:

  • 你能在变量初始化后放一个断点并检查Update.Email的值吗?
  • 该代码中有几个错误。您可以通过using parameters 解决几乎所有问题,而不是尝试通过字符串连接来组装 SQL。
  • 也许将''" + Update.Email + "'' 更改为'" + Update.Email + "'
  • xkcd.com/327 - 使用参数而不是这样构造查询

标签: c# .net sql-server tsql


【解决方案1】:

此查询失败的原因可能有多种 您正在使用 '''+@Email+''' SQL server 将 '' 更改为 ' 这意味着当您传递 ''' 时,它会转换为 '' 如果你想在查询中传递一个字符串变量,它应该像

WHERE Email = '" + Update.Email + "'

这样可以作为字符串传递 第二种选择是你可以在程序中发送所有参数,根据数据可以执行你的查询,以后维护和理解会容易得多

【讨论】:

  • 谢谢,今晚我将根据反馈重新编写动态 SQL 语句。我现在正在工作,所以我无法找到解决方案,但感谢您的反馈。
【解决方案2】:

我找到了解决问题的方法。根据建议的反馈,我想出了这个:

 try
    {
        foreach (Base_Item item in Game_Data._Item_Drop)
        {
            //Recipe
            if (item.Name.Contains("Recipe"))
            {
                if (Update_Recipe(item.Name))
                {
                    uri = Game_Data._EndPoint + "value";
                    Update.Value_1 = "1";//Update.Value_1 + "UPDATE Skill_Gemology SET " + item.Name + "= 1 WHERE Email = ''" + Update.Email + "'' ";
                    Update.Value_2 = "Skill_Gemology";
                    Update.Value_3 = item.Name;
                }
            }
            //Rune
            else if (item.Name.Contains("Rune") || item.Name == "Polished_Ancient_Stone" || item.Name == "Ancient_Stone")
            {
                uri = Game_Data._EndPoint + "value";
                Update.Value_1 = item.Count.ToString();//Update.Value_1 + "UPDATE [dbo].[Inventory_Runes] SET [" + item.Name + "] = [" + item.Name + "] + " + item.Count.ToString() + " WHERE Email = ''" + Update.Email + "''";
                Update.Value_2 = item.Name;
            }

            StartCoroutine(booleanwebrequest(uri, Update));
            Debug.Log(Update);
        }
    }
    catch (Exception ex)
    {
        Debug.Log(ex);
    }        

API 后端:

 public bool Save_Item_Drop(string Email, string value, string column)
    {
        try
        {
            SqlConnection SQLConn = new SqlConnection(cn);
            SqlCommand cmd = new SqlCommand("spHere", SQLConn);
            bool Success;

            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@Email", Email);
            cmd.Parameters.AddWithValue("@Value", value);
            cmd.Parameters.AddWithValue("@Column", column);

            SQLConn.Open();
            Success = Convert.ToBoolean(cmd.ExecuteScalar());
            SQLConn.Close();

            return Success;
        }
        catch (Exception ex)
        {
            string _Product = "White Box Gaming API";
            dynamic _Method = Convert.ToString(System.Reflection.MethodBase.GetCurrentMethod().Name);
            dynamic _Class = Convert.ToString(this.GetType().Name);
            string _Exception = Convert.ToString(ex.ToString());

            Log_Product_Exception(_Product, _Class, _Method, _Exception);
            return false;
        }
    }

SQL:

    ALTER PROCEDURE [dbo].[spHere]
    @Email AS NVARCHAR(500),
    @Value AS NVARCHAR(1000),
    @Column As NVARCHAR(1000)
AS
BEGIN
    DECLARE @Response AS BIT = 0    
    DECLARE @Statement AS NVARCHAR(MAX)

SET @Statement = 'UPDATE Inventory_Runes SET ' + @Column + ' = ' + @Column + ' + ' + @Value + ' WHERE Email = ''' + @Email + ''''

-------Pre Check-----------------------------------------------------------------------------------------------------
    --Runes
    IF Not EXISTS(SELECT Email FROM [dbo].[Inventory_Runes] WHERE Email = @Email) BEGIN
        INSERT INTO [dbo].[Inventory_Runes] (Email) VALUES (@Email)
    END

BEGIN TRY
    EXECUTE sp_executesql @Statement
    SET @Response = 1
END TRY
BEGIN CATCH
    SET @Response = 0
END CATCH

    SELECT @Response
END 

【讨论】:

  • 提示:将对象名称组装成动态 SQL 语句时的最佳做法是使用 QuoteName() 以避免出现奇怪名称的问题,例如New Table 带有空格或保留字,例如 From
猜你喜欢
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 2011-05-11
  • 2016-12-13
相关资源
最近更新 更多