.net 存储过程偶尔执行两次

.net 存储过程偶尔执行两次,.net,sql-server,stored-procedures,.net,Sql Server,Stored Procedures,我创建了一个.net控制台应用程序,它从计算机和/或用户收集一些基本的库存信息。它通过存储过程将此信息转储到SQL Server 2012数据库中 我偶尔会在至少两个表中出现重复记录 存储过程非常简单,当存储过程接收到序列号(以及其他参数)时,它会在资产表中搜索序列号。如果找到匹配项,则返回assetId,否则将创建新条目并返回新创建的assetId。同样在该过程中,使用先前返回的assetId将日期时间条目添加到事件表中 我开始看到的是资产表中的两条记录,它们具有顺序编号,但序列号相同。有趣的

我创建了一个.net控制台应用程序,它从计算机和/或用户收集一些基本的库存信息。它通过存储过程将此信息转储到SQL Server 2012数据库中

我偶尔会在至少两个表中出现重复记录

存储过程非常简单,当存储过程接收到序列号(以及其他参数)时,它会在资产表中搜索序列号。如果找到匹配项,则返回
assetId
,否则将创建新条目并返回新创建的
assetId
。同样在该过程中,使用先前返回的
assetId
将日期时间条目添加到事件表中

我开始看到的是资产表中的两条记录,它们具有顺序编号,但序列号相同。有趣的是,事件表中将有两条记录,分别对应于具有完全相同的日期时间的
assetId

在我们拥有的22000多台计算机中,这只发生在五个序列号上,所以对我来说,这不是世界末日。然而,由于这个问题,我一直在质疑其余数据的可靠性

你知道这是怎么发生的吗

存储过程

    --Create an asset row if there is not one and retrieve the id. Or just retrieve the id.
If (select count(assetid) from asset where serial=@serial) > 0
Begin
    set @assetid = (select top 1 assetid from asset where serial=@serial )
End
Else 
    --Add asset to table
    Begin
        Insert into asset (serial, model, manufacturer) 
        values (@serial, @model, @manufacturer);

        set @assetid = (Select SCOPE_IDENTITY())
    End
    --End Asset entry

    --Insert Audit Event record
    Insert into auditevent (assetid, audittime, username, computername, operatingsystem) 
    values (@assetid, @audittime, @username, @computername, @operatingsystem)

    Declare @auditeventid int = (select SCOPE_IDENTITY())

    --Send the ipString to the function that will convert it to a table and insert into IP Table
    Insert into ipaddress (auditeventid, ipaddress) 
        select * 
        from CsvToTable(@auditeventid, @ipaddressvalues)
控制台应用程序(单线程)


如果不查看控制台应用程序的代码及其运行细节,就很难诊断此问题。例如,您是否可以运行多个实例并让两个线程尝试同时执行同一任务

当有库存项目要添加时,您可以通过运行控制台应用程序两次来测试这是否是原因,并查看它是否重复

存储过程的逻辑似乎很好,但我会重新编写它:

IF EXISTS (SELECT 1 FROM asset WHERE serial=@serial) 
   -- Create an asset row if it doesn't exist
    BEGIN
        SELECT @assetid = assetid FROM asset WHERE serial=@serial
    END
ELSE 
    --Add asset to table    
    BEGIN
        INSERT INTO asset (serial,model,manufacturer) 
        VALUES (@serial,@model,@manufacturer);

        SELECT @assetid = SCOPE_IDENTITY()
    END

这是未经测试的,但您应该明白。

为什么要从应用程序进行审核,这是一个数据库反模式?我建议将
asset.assetid
作为主键,以避免重复,即使在其他地方有bug。我还建议用
begintransaction
/
commit
包装所有语句。顺便说一句,我认为问题在于调用存储过程的控制台应用程序,或者控制台应用程序是如何触发执行的。@HLGEM我不知道有任何其他方法可以快速完成任务。我考虑了一个服务器驱动的模型,但需要更多的代码和调试,这意味着时间。什么是更好的模型?@wdosanjos asset.assetid实际上是PK。我认为重复的记录实际上是不同的,因为assetid字段增加了1。请参阅上面我添加的控制台代码。这是一个非常简单的程序。它是单线程的,所以没有运行任何函数两次。它从WMI收集数据,存储到变量,并通过存储过程保存到db。
IF EXISTS (SELECT 1 FROM asset WHERE serial=@serial) 
   -- Create an asset row if it doesn't exist
    BEGIN
        SELECT @assetid = assetid FROM asset WHERE serial=@serial
    END
ELSE 
    --Add asset to table    
    BEGIN
        INSERT INTO asset (serial,model,manufacturer) 
        VALUES (@serial,@model,@manufacturer);

        SELECT @assetid = SCOPE_IDENTITY()
    END