2014-08-28 115 views
0

我已经创建了一个.net控制台应用程序,用于从计算机和/用户收集一些基本清单信息。它通过存储过程将此信息转储到SQL Server 2012数据库中。存储过程偶尔会执行两次

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

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

我开始看到的是资产表中的两条记录,其序号为assetId,但具有相同的序列号。有趣的是,事件表中将有两个记录对应于这些assetId的每一个都具有相同的完全相同的date_time

在我们拥有的22,000多台电脑中,这只发生在五个序列号上,所以对我来说这不是世界末日。但是,由于这个问题,我一直对其余数据的可靠性提出质疑。

任何想法如何发生?

存储过程

--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 [email protected]) > 0 
Begin 
    set @assetid = (select top 1 assetid from asset where [email protected]) 
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) 

控制台应用程序(单线程)

Dim strExcutionCommand As String = "dbo.auditclient @computername=N'" & strComputerName & "',@modeltext=N'" & strModel & "',@serial=N'" & strSerialNumber & "',@username=N'" & strUserName & "',@manufacturertext=N'" & strManufacturer & "',@operatingsystemtext=N'" & strOperatingSystem & "',@ipaddressvalues=N'" & strNetAddress & "'" 


    Dim Inv_ConnectString As String = "Data Source=cen-support01;Initial Catalog=IT_Inventory;User Id=" & strSqlUser & ";Password=" & strSqlPw & ";" 
    Dim myConnection As SqlConnection = New SqlConnection(Inv_ConnectString) 

    Dim myCommand As SqlCommand = New SqlCommand(strExcutionCommand, myConnection) 
    myConnection.Open() 
    myCommand.ExecuteNonQuery() 
    myConnection.Close() 
+0

你为什么要从应用程序进行审计,即数据库反模式? – HLGEM 2014-08-28 15:14:19

+0

我建议将'asset.assetid'作为主键,以避免重复,即使其他地方存在错误。我还建议用'begin transaction' /'commit'包装所有的语句。 – wdosanjos 2014-08-28 15:22:22

+0

顺便说一句,我认为问题是调用存储过程的控制台应用程序,或控制台应用程序如何触发执行。 – wdosanjos 2014-08-28 15:23:44

回答

0

这并不容易诊断这个问题没有对如何细节一起看到代码控制台应用程序它运行。例如,您是否可以运行多个实例并让2个线程同时尝试执行相同的任务?

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

存储过程的逻辑似乎很好,虽然我不是有点重新写:

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

     SELECT @assetid = SCOPE_IDENTITY() 
    END 

这是未经测试,但你应该明白我的意思。

+0

查看我上面添加的控制台代码。这是一个非常简单的程序。它是单线程的,所以没有两次运行任何函数。它从WMI收集数据,存储到变量并通过存储过程保存到数据库。 – 2014-08-29 15:49:10