C# 向数据库插入/更新数据的最佳方式是什么

C# 向数据库插入/更新数据的最佳方式是什么,c#,sql,database,performance,C#,Sql,Database,Performance,鉴于我们有下表: CREATE TABLE TestData ( ID INT NOT NULL PRIMARY KEY, Value INT ) 在将数据写入表时,如果ID已经存在,我将尝试更新表,或者插入一个新行 我在生产代码中编写或遇到了几个选项: 首先执行更新查询,如果没有更新行,则执行插入查询 int affectedRows = 0; using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET

鉴于我们有下表:

CREATE TABLE TestData 
(
    ID INT NOT NULL PRIMARY KEY,
    Value INT
)
在将数据写入表时,如果ID已经存在,我将尝试
更新表,或者
插入一个新行

我在生产代码中编写或遇到了几个选项:

  • 首先执行
    更新
    查询,如果没有更新行,则执行
    插入
    查询

  • int affectedRows = 0;
    using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
    {
        try
        {
            // ...add params
            affectedRows = updateCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
        {
            try
            {
                // ...add params
                affectedRows = insertCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }  
    
    int affectedRows = 0;
    using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
    {
        try
        {
            // ... add params
            affectedRows = insertCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
        {
            try
            {
                // ...add params
                affectedRows = updateCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }
    
    bool dataExist = false;
    // ... 
    using (IDbCommand selectCmd = new SqlCommand("SELECT ID FROM TestDate WHERE ID=@ID", myConn))
    {
        try
        {
            // ... add param
            using (IDataReader reader = selectCmd.ExecuteReader())
                dataExist = reader.Read();
        }
        catch (SqlException) { /*...*/ }
    }
    if (dataExist) { /* update query, similar to above one*/ }
    else { /* insert, similar to above one */ }
    
  • 首先执行
    Insert
    查询,如果失败,则执行
    Insert
    查询

  • int affectedRows = 0;
    using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
    {
        try
        {
            // ...add params
            affectedRows = updateCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
        {
            try
            {
                // ...add params
                affectedRows = insertCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }  
    
    int affectedRows = 0;
    using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
    {
        try
        {
            // ... add params
            affectedRows = insertCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
        {
            try
            {
                // ...add params
                affectedRows = updateCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }
    
    bool dataExist = false;
    // ... 
    using (IDbCommand selectCmd = new SqlCommand("SELECT ID FROM TestDate WHERE ID=@ID", myConn))
    {
        try
        {
            // ... add param
            using (IDataReader reader = selectCmd.ExecuteReader())
                dataExist = reader.Read();
        }
        catch (SqlException) { /*...*/ }
    }
    if (dataExist) { /* update query, similar to above one*/ }
    else { /* insert, similar to above one */ }
    
  • 首先使用新ID执行
    选择
    查询,然后如果行存在,则执行
    更新
    其他
    插入
    查询

  • int affectedRows = 0;
    using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
    {
        try
        {
            // ...add params
            affectedRows = updateCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
        {
            try
            {
                // ...add params
                affectedRows = insertCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }  
    
    int affectedRows = 0;
    using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
    {
        try
        {
            // ... add params
            affectedRows = insertCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
        {
            try
            {
                // ...add params
                affectedRows = updateCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }
    
    bool dataExist = false;
    // ... 
    using (IDbCommand selectCmd = new SqlCommand("SELECT ID FROM TestDate WHERE ID=@ID", myConn))
    {
        try
        {
            // ... add param
            using (IDataReader reader = selectCmd.ExecuteReader())
                dataExist = reader.Read();
        }
        catch (SqlException) { /*...*/ }
    }
    if (dataExist) { /* update query, similar to above one*/ }
    else { /* insert, similar to above one */ }
    
  • 执行一个大查询以执行所有选择更新或插入操作

  • string query = "IF EXISTS (SELECT ID FROM TestData WHERE ID=@ID) " +
                   "UPDATE TestData SET Value = @Value WHERE ID = @ID " +
                   "ELSE INSERT INTO TestData VALUES (@ID, @Value)";
    
    using (IDbCommand bigQueryCmd = new SqlCommand(query, myConn))
    {
        try
        {
            // ... add param
            bigQueryCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    我的问题是,在上述选项(或您自己的方法)中,什么是
    最佳实践
    最有效的
    首选方法

    上述选项的示例代码:

    (1) 首先执行
    更新
    查询,如果没有更新行,则执行
    插入
    查询

    int affectedRows = 0;
    using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
    {
        try
        {
            // ...add params
            affectedRows = updateCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
        {
            try
            {
                // ...add params
                affectedRows = insertCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }  
    
    int affectedRows = 0;
    using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
    {
        try
        {
            // ... add params
            affectedRows = insertCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
        {
            try
            {
                // ...add params
                affectedRows = updateCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }
    
    bool dataExist = false;
    // ... 
    using (IDbCommand selectCmd = new SqlCommand("SELECT ID FROM TestDate WHERE ID=@ID", myConn))
    {
        try
        {
            // ... add param
            using (IDataReader reader = selectCmd.ExecuteReader())
                dataExist = reader.Read();
        }
        catch (SqlException) { /*...*/ }
    }
    if (dataExist) { /* update query, similar to above one*/ }
    else { /* insert, similar to above one */ }
    
    (2) 首先执行
    Insert
    查询,如果失败,则执行
    Insert
    查询

    int affectedRows = 0;
    using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
    {
        try
        {
            // ...add params
            affectedRows = updateCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
        {
            try
            {
                // ...add params
                affectedRows = insertCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }  
    
    int affectedRows = 0;
    using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
    {
        try
        {
            // ... add params
            affectedRows = insertCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
        {
            try
            {
                // ...add params
                affectedRows = updateCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }
    
    bool dataExist = false;
    // ... 
    using (IDbCommand selectCmd = new SqlCommand("SELECT ID FROM TestDate WHERE ID=@ID", myConn))
    {
        try
        {
            // ... add param
            using (IDataReader reader = selectCmd.ExecuteReader())
                dataExist = reader.Read();
        }
        catch (SqlException) { /*...*/ }
    }
    if (dataExist) { /* update query, similar to above one*/ }
    else { /* insert, similar to above one */ }
    
    (3) 首先使用新ID执行
    选择
    查询,然后如果行存在,则执行
    更新
    其他
    插入
    查询

    int affectedRows = 0;
    using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
    {
        try
        {
            // ...add params
            affectedRows = updateCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
        {
            try
            {
                // ...add params
                affectedRows = insertCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }  
    
    int affectedRows = 0;
    using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
    {
        try
        {
            // ... add params
            affectedRows = insertCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    if (affectedRows == 0)
    {
        using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
        {
            try
            {
                // ...add params
                affectedRows = updateCmd.ExecuteNonQuery();
            }
            catch (SqlException) { /*...*/ }
        }
    }
    
    bool dataExist = false;
    // ... 
    using (IDbCommand selectCmd = new SqlCommand("SELECT ID FROM TestDate WHERE ID=@ID", myConn))
    {
        try
        {
            // ... add param
            using (IDataReader reader = selectCmd.ExecuteReader())
                dataExist = reader.Read();
        }
        catch (SqlException) { /*...*/ }
    }
    if (dataExist) { /* update query, similar to above one*/ }
    else { /* insert, similar to above one */ }
    
    (4) 执行一个大查询以执行所有选择更新或插入操作

    string query = "IF EXISTS (SELECT ID FROM TestData WHERE ID=@ID) " +
                   "UPDATE TestData SET Value = @Value WHERE ID = @ID " +
                   "ELSE INSERT INTO TestData VALUES (@ID, @Value)";
    
    using (IDbCommand bigQueryCmd = new SqlCommand(query, myConn))
    {
        try
        {
            // ... add param
            bigQueryCmd.ExecuteNonQuery();
        }
        catch (SqlException) { /*...*/ }
    }
    
    您可以使用

    基于目标表对目标表执行插入、更新或删除操作 关于与源表联接的结果

    出于并发原因,使用
    MERGE
    如果存在/UPDATE/INSERT
    要好得多,而且它只是一条语句,因此需要维护的代码更少:

    比如:

    CREATE TABLE TestData (
       ID INT NOT NULL PRIMARY KEY,
       Value INT);
    
    INSERT INTO TestData
    VALUES (1,3);
    
    
    DECLARE @id INT = 1, @value INT = 10;    -- will update
    --DECLARE @id INT = 2, @value INT = 10;  -- will insert
    
    ;MERGE TestData AS TGT
    USING (SELECT * FROM (SELECT @id AS ID, @value AS VALUE) AS t) AS SRC
       ON TGT.ID = SRC.ID
    WHEN MATCHED THEN
       UPDATE SET Value = SRC.[VALUE]
    WHEN NOT MATCHED THEN
       INSERT (ID, [VALUE])
       VALUES (SRC.ID, SRC.[VALUE]);
    
    SELECT *
    FROM TestData;
    

    检查您是否可以为我使用
    MERGE
    。没有,因为您的代码很容易被SQL注入!如果您克服了这个问题,那么您可以创建一个存储过程,并在其中创建更新和插入逻辑。这是一个直接向表中插入新数据的过程。我应该从哪里合并?与派生表合并这是从C#调用的一个大查询吗?是的,您需要绑定参数,它应该可以工作。但首先使用SSMSI检查是否知道合并会起作用,问题是它是否比其他方法更好。我发现它非常类似于第四个选项(如果存在/UPDATE/INSERT)@VietNguyen MERGE只是一条语句,使用隐式事务完成。如果您有并发应用程序,并且在存在/更新/插入时使用多部分,该怎么办。一个查询可以在另一个查询插入数据时检查是否存在