【问题标题】:Need Help On How To If Record Exists Update Else Insert需要帮助如果记录存在更新其他插入
【发布时间】:2017-05-16 03:42:02
【问题描述】:

需要在 c# 中进行编程的最佳方法。我正在尝试执行 if record exists update 语句 else insert 语句,更新代码但仍然有插入/更新到数据库的问题。从此代码执行后,数据库中没有任何显示:

        String updCmdTxt = "UPDATE..";
        String insertCmdTxt = "INSERT ..";
        using (var scope = new TransactionScope())
        {
            using (var con = new OracleConnection(strConnection))
            {
                bool isDuplicate = false;
                var insertcmd = new OracleCommand(insertCmdTxt, con);
                try
                {


                    con.Open();
                          ......add params

                    insertcmd.ExecuteNonQuery();

                    con.Close();
                    Response.Redirect("test.aspx?Id=" + labelRID.Text);
                }
                catch (OracleException x)
                {
                    isDuplicate = true; //determine if the exception is about duplicates.
                    if (!isDuplicate)
                    {
                        throw;
                    }
                }
                finally
                {
                    insertcmd?.Dispose();
                }
                if (isDuplicate)
                {
                    using (var updcmd = new OracleCommand(updCmdTxt, con))

                        {

                       ....
                      updcmd.ExecuteNonQuery();


                    }
                }
                scope.Complete();
                Response.Redirect("test.aspx?Id=" + labelRID.Text);

            }
        }
    }

有没有更好的编程方法?如果有,怎么做?

【问题讨论】:

  • 2 件事:1. 确保您的 rid 字段具有唯一约束。 2. 在您的else 块中(INSERT 操作)捕获并处理duplicate row exception。如果在您的第​​一次检查 SELECT COUNT 和您的插入/更新操作之间有可能另一个客户端/连接/线程可能已经进行了插入,那么这些很重要。
  • 也是一种优化:您可以重复使用与检查计数相同的连接来插入或更新。请注意,如果您要从最后插入的行中检索自动递增的 ID,则必须确保该连接没有在另一个线程上使用。
  • 你可以用oracle合并语句做你想做的事
  • 有没有例子说明如何在c#中做oracle合并语句
  • 这个问题仍然存在。它不是插入或更新到数据库中。看看我上面更新的代码,让我知道我做错了什么。谢谢

标签: c# oracle


【解决方案1】:

如果不了解所有细节(例如重复概率、每秒请求数等),很难给出建议。我使用了一些常用技术来实现这一点:

  • 一个封装“upsert”工作流的存储过程。见Oracle: how to UPSERT

  • 在客户端(您的情况)上实现 upsert 逻辑,但为了保证一致性,您需要启动事务并在执行操作后关闭它。

如果表中存在的行更有可能,在插入之前使用更新以避免频繁的异常。否则,您可以通过在更新前使用插入来优化工作流程。

悲观解

String updCmdTxt = "UPDATE ....";
String insertCmdTxt = "INSERT ....";
using (var scope = new TransactionScope())
{ 
   using (var con = new OracleConnection(conStr)){
      int rows;
      using (var updcmd = new OracleCommand(updCmdTxt, con)){
         //Set parameters ...
         rows = updcmd.ExecuteNonQuery();
      }
      //If update command did not affect any rows, insert
      if (rows == 0) {
         using (var insertcmd = new OracleCommand(insertCmdTxt, con)){
            // Set parameters...
            insertcmd.ExecuteNonQuery();
         }
      }
      scope.Complete();
   }
}

乐观解决方案

String updCmdTxt = "UPDATE ....";
String insertCmdTxt = "INSERT ....";
using (var scope = new TransactionScope())
{
    using (var con = new OracleConnection(conStr))
    {
        bool isDuplicate = false;
        var insertcmd = new OracleCommand(insertCmdTxt, con);
        try
        {
            // Set parameters...
            insertcmd.ExecuteNonQuery();
        }
        catch (OracleException x)
        {
            isDuplicate = ...; //determine if the exception is about duplicates.
            if (!isDuplicate)
            {
                throw;
            }
        }
        finally
        {
            insertcmd?.Dispose();
        }
        if (isDuplicate)
        {
            using (var updcmd = new OracleCommand(updCmdTxt, con))
            {
                //Set parameters ...
                updcmd.ExecuteNonQuery();
            }
        }
        scope.Complete();
    }
}

【讨论】:

  • 至于重复我想避免重复。概率不大。这是我能告诉你的最好的了。
  • 我的意思是重复插入已经在表中的记录。我提供的示例将允许您避免重复和竞争条件。
  • 我认为这会起作用并有所帮助。还有一个问题。我在 updCmdText 上收到错误:
  • 我认为这会起作用并有所帮助。还有一个问题。我在 updCmdText 上收到错误:“当前上下文中不存在该名称”。这需要设置在某个地方吗?
  • updCmdTextinsertCmdTxt 是包含更新和插入命令的字符串变量
【解决方案2】:

使用 MERGE 语句,它结合了 INSERT 和 UPDATE 语句的功能。例如:

MERGE INTO CONTRACT_INFO c
  USING (SELECT 12345 FROM DUAL AS RID) d
    ON (d.RID = c.RID)
  WHEN MATCHED THEN
    UPDATE
      SET CONTRACT_INFO_FIELD_1 = something,
          CONTRACT_INFO_FIELD_2 = something_else
  WHEN NOT MATCHED THEN
    INSERT (RID, CONTRACT_INFO_FIELD_1, CONTRACT_INFO_FIELD_2)
    VALUES (d.RID, something, something_else);

祝你好运。

【讨论】:

  • MERGE 是 Oracle 中的原子操作吗?我没有处理过 Oracle,但在 MSSQL 中它不是原子的。
  • 我对此表示怀疑 - 但是,与任何其他 DML 语句一样,它是事务处理的。为什么这对你很重要? And have you checked this answer?
猜你喜欢
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 2011-04-07
  • 2020-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
相关资源
最近更新 更多