我应该在保存之前检查是否存在,或者只是在重复密钥违规时捕获异常?

时间:2017-10-02 03:29:26

标签: c# sql sql-server soap

哪种方法可以更快地阻止重复事务?我有一个基于SOAP的网关,它接收以下请求:

  <soap:Body>
    <ProcessItem>
      <Item>
        <ItemType>int</ItemType>
        <ItemName>string</ItemName>
      </Item>
    </ProcessItem>
  </soap:Body>

现在我不能保存具有相同名称和类型值的项目。我有两个选择:

  1. 进行验证,从而以编程方式防止重复 - 例如:

        if (!ItemReposioty.Exists(concreteItem))
        {
            ItemRepository.Save(concreteItem);
        }
        else
        {
            return DuplicateStatus(); 
        }
    
  2. 在MS SQL Server表中使用唯一约束或索引,使字段类型和名称唯一,从而防止在数据库级别重复。

    try 
    {
        ItemRepository.Save(newItem); 
    } 
    catch (SqlException e) 
    {
        return DuplicateStatus(); 
    } 
    
  3. 你会做什么?

2 个答案:

答案 0 :(得分:1)

将它放在数据库端是最好的方法。如果两个代码实例同时运行怎么办?您仍然可能会获得重复项。

并且,如果将来创建另一个更新数据库的进程,绕过您的代码,它可能不会检查重复项。

将唯一索引放在数据库上可确保不会发生重复。在尝试插入之前,您仍然可以检查重复项,但数据库应该有最终决定权。

答案 1 :(得分:1)

为了直接回答你的问题,我认为在大多数情况下,后一种方式可能更快,因为它不需要进行两次数据库调用。

我会选择以前的方式,虽然我当然也会设置正确的数据库方面的约束。我认为(尽管不确定)ORM或其他操作背后的代码可以有效地执行 - 也就是说,我希望存在检查比写操作快得多。此外,与HTTP请求的整体延迟相比,通过LAN访问数据库的速度很快,因此弄清楚如何将两个数据库操作合并为一个可能是天真的优化。

在后一种情况下,您需要确保导致的SqlException是由于重复的密钥冲突 - 其他SqlExceptions可能由于其他原因而发生,并且您可能不希望以相同的方式处理它们。

为了使前一个解决方案更加健壮,您可能希望在事务中执行这两个操作,以便可以保留来自第一个查询的任何锁定,并且使用存在性检查进行原子更新。