C# 使用C在数据库中插入记录时使用事务#

C# 使用C在数据库中插入记录时使用事务#,c#,sql,sql-server,tsql,transactions,C#,Sql,Sql Server,Tsql,Transactions,我从未使用过SQL事务,就我而言,我知道我真的必须使用它们。我的应用程序的一个功能是将Excel文件转换为数据库 因此,我从Excel中获取值,构建一个字符串数组,其中包含参数(将发送到SP)和一些我将直接插入主表的值,以及其他我将插入辅助表的值,然后我将获取id,这些id将代替主表中的值。我想说的是我有外键,这就是为什么我要这么做 所以我认为我做得很完美,但没有交易。但是,如果在表中插入值时出现任何错误,我将不得不执行回滚 所以在这个过程中,我使用了5个存储过程,每个表一个。这些SP并不是此过

我从未使用过SQL事务,就我而言,我知道我真的必须使用它们。我的应用程序的一个功能是将Excel文件转换为数据库

因此,我从Excel中获取值,构建一个字符串数组,其中包含参数(将发送到SP)和一些我将直接插入主表的值,以及其他我将插入辅助表的值,然后我将获取id,这些id将代替主表中的值。我想说的是我有外键,这就是为什么我要这么做

所以我认为我做得很完美,但没有交易。但是,如果在表中插入值时出现任何错误,我将不得不执行回滚

所以在这个过程中,我使用了5个存储过程,每个表一个。这些SP并不是此过程的专有。它们将在应用程序中用于插入记录

但我需要在哪里使用事务的帮助。我应该在C#(应用程序端)还是在SQL Server(服务器端)中执行此操作

现在,我使用的是C#中的SqlTransaction对象,它在某种程度上起作用,因为如果我执行回滚,他实际上会取消所有插入,但我在事务中使用的ID不再可用。只有我删除所有表并再次创建它们,这些ID才会再次可用


因此,我认为我没有很好地使用事务,这就是为什么我需要帮助,知道如何更好地使用事务,以及在哪里更好地使用事务。

我认为您使用事务的方式是正确的,问题是标识列的种子没有回滚

我猜您正在使用MS SQL Server?要在不重新创建表的情况下重置标识列,可以使用DBCC CHECKIDENT

DBCC CHECKIDENT (table_name, RESEED, 99);
这将重置种子,以便分配的下一个标识值为100。当然,您必须在开始事务之前记录表的最高标识值


我只会在只有一个writer进程的情况下使用它。在多个writer的情况下,除非首先执行一些严重的表锁定,否则很可能会使事情变得很糟糕。如果有多个编写器,我认为您最好编写代码的其余部分,这样标识列值中的“漏洞”是可以接受的。

如果您没有将标识列用于其他目的,并且不绝对要求它是连续的,请试着习惯它将具有“缺少”值的想法。它们并不是真的丢失了,因为它们只是提供了一种给每个记录一个廉价的唯一密钥的方法。当记录也被删除时,您将得到间隙,因此也不应该依赖标识列作为记录计数器

当我们查看表时,让我们的大脑看到序列号是很好的,但是成本是您自己和数据库引擎的额外工作。我花了几个月才接受

该值未被重用的原因是,当该列用作外键时,有助于提供数据库完整性。

[只有当我删除所有表并再次创建它们时,这些ID才会再次可用。]完全正确,这就是标识列的工作方式。如果你问这个问题,你需要去读一些书