代码之家  ›  专栏  ›  技术社区  ›  Yuriy Faktorovich

检查级联存储错误的正确方法是什么?

  •  0
  • Yuriy Faktorovich  · 技术社区  · 16 年前

    编辑:我应该提到这将在多台机器上同时运行,我希望它支持不同的数据库。

    编辑2:我的解决方案最终使用了一个锁来检查重复项。存储过程是一种选择,但我不想将业务逻辑放入数据库中。我为其他人评论说,我知道网络农场中的种族状况,但这种罕见的情况不值得进一步研究。

    4 回复  |  直到 16 年前
        1
  •  2
  •   Keith Adler    16 年前

    异常处理应用于捕获非主要场景,例如数据库关闭或命令超过超时时间。如果您对用户的唯一性和电子邮件的唯一性有限制,那么您应该在提交数据之前对其进行测试。依靠检查/索引约束作为处理这些场景的一种方式,将在长期内造成混乱。此外,错误处理的一个关键最佳实践是永远不要让最终用户知道错误发生的具体原因。

        2
  •  1
  •   Robert Rossney    16 年前

    BEGIN TRANSACTION
    IF EXISTS (SELECT UserID FROM User WHERE UserID = @UserID)
       BEGIN
          ROLLBACK
          SELECT 'User already exists in the User table.'
          RETURN 1
       END
    
    IF EXISTS (SELECT UserID FROM Email WHERE UserID = @UserID)
       BEGIN
          ROLLBACK
          SELECT 'User already exists in the Email table.'
          RETURN 2
       END
    
    INSERT INTO User ...
    INSERT INTO Email ...
    COMMIT
    RETURN 0
    

        3
  •  0
  •   Justin Niessner    16 年前

    您应该在您的业务逻辑中的某个地方捕捉到这种情况,而不是仅仅依靠数据库来提供您正在查找的错误。

        4
  •  0
  •   Steve    16 年前

    我不会依赖表约束进行数据验证。在插入之前使用查询验证数据。异常是创建的昂贵对象。另外,我更喜欢有适当的约束来防止无效数据,而不是验证。我认为约束是桌子的安全带。只有在发生错误时才应该调用它。业务逻辑应该在插入之前验证所有数据。如果目标数据库可能不支持存储过程,请不要依赖存储过程。

    这是我处理这件事的一般方法。

            private void Form1_Load(object sender, EventArgs e)
        {
            OleDbConnection conn = null;
            OleDbTransaction t = null;
            try
            {
                conn = new OleDbConnection("a database");
    
                conn.Open();
    
                //query both tables to prevent insert fail, 
                //obviously UserID should be parameter.
                var cmd = new OleDbCommand("select count(*) from User where UserID = 1", conn);
                var count = (double)cmd.ExecuteScalar();
    
                cmd.CommandText = "select count(*) from Email where UserID = 1";
                count += (double)cmd.ExecuteScalar();
    
                if (count != 0)
                {
                    MessageBox.Show("Record exists");
                    return;
                }
    
                t = conn.BeginTransaction();
    
                //insert logic goes here
    
    
                t.Commit();
            }
            catch (Exception x)
            {
                //we still need catch block, someone else may have updated the 
                //data after you checked but before you insert or db open may 
                //fail
    
                MessageBox.Show(x.Message);
                if (t != null)
                    t.Rollback();
            }
            finally
            {                
                if (conn != null)
                    conn.Close();
            }
        }