我有一个存储过程,我正在从VB.NET执行。 SP应将记录插入表中并将一组返回给调用应用程序。返回的集合是插入的记录。
如果INSERT
失败,则会在SP中捕获并重新抛出异常,但我从未在应用程序中看到异常。严重性级别为14,所以我应该看到它。
这是存储过程:
BEGIN TRY
BEGIN TRANSACTION
-- Declare local variables
DECLARE @DefaultCategoryID AS BIGINT = 1 -- 1 = 'Default Category' (which means no category)
DECLARE @DefaultWeight AS DECIMAL(18,6) = 0
DECLARE @InsertionDate AS DATETIME2(7) = GETDATE()
DECLARE @SendToWebsite AS BIT = 0 -- 0 = 'NO'
DECLARE @MagentoPartTypeID AS BIGINT = 1 -- For now, this is the only part type we are importing from COPICS ('simple' part type)
DECLARE @NotUploaded_PartStatusID AS TINYINT = 0 -- 0 = 'Not Uploaded'
DECLARE @Enabled_PartStatusID AS TINYINT = 1 -- 1 = 'Enabled'
DECLARE @Disabled_PartStatusID AS TINYINT = 2 -- 2 = 'Disabled'
-- Get the part numbers that will be inserted (this set will be returned to calling procedure).
SELECT c.PartNumber
FROM
COPICSPartFile c
LEFT JOIN Part p on c.PartNumber = p.PartNumber
WHERE
p.PartNumber IS NULL
-- Insert new records from COPICSPartFile (records that don't exist - by PartNumber - in Part table)
INSERT INTO Part
([PartNumber]
,[ReplacementPartNumber]
,[ShortDescription]
,[ListPrice]
,[PartStatusTypeID]
,[Weight]
,[CategoryID]
,[DateInserted]
,[SendToWebsite]
,[FileName]
,[MagentoPartTypeID]
,[PrintNumber])
SELECT
c.PartNumber
,c.ReplacementPartNumber
,c.ShortDescription
,c.ListPrice
,CASE WHEN c.PartStatusTypeID = @Enabled_PartStatusID THEN @NotUploaded_PartStatusID ELSE @Disabled_PartStatusID END
,@DefaultWeight
,@DefaultCategoryID
,@InsertionDate
,@SendToWebsite
,@FileName
,@MagentoPartTypeID
,c.PrintNumber
FROM
COPICSPartFile c
LEFT JOIN Part p on c.PartNumber = p.PartNumber
WHERE
p.PartNumber IS NULL
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
THROW;
END CATCH
这是.net代码:
Try
'Create command
Dim command As New SqlCommand
command.CommandType = CommandType.StoredProcedure
conn = New SqlConnection(m_ConnectionString)
command.Connection = conn
command.CommandText = "trxInsertPartFromCOPICSPartFile"
With command.Parameters
.AddWithValue("@FileName", fileName)
End With
Dim da As New SqlDataAdapter(command)
Dim dt As New DataTable
da.Fill(dt)
If dt.Rows.Count > 0 Then
Return dt
Else
Return Nothing
End If
Catch ex As SqlException
Dim myMessage As String = ex.Message
Finally
If conn.State <> ConnectionState.Closed Then
conn.Close()
End If
End Try
当我试图弄清楚为什么异常(重复键)没有被我的应用程序捕获时,我尝试在SELECT
之前在SP中发表INSERT
语句瞧。应用程序中捕获了INSERT
的异常。
有人可以向我解释为什么SELECT
声明会导致这种情况吗?我知道我可以将SELECT
分解为另一个SP,但如果可能的话,我想保留所有原子事务。这是预期的行为吗?有办法吗?
感谢。
答案 0 :(得分:1)
Fill
方法吞噬了异常。不要使用该方法,而是创建SqlDataReader
,执行command.ExecuteReader()
,然后使用阅读器通过DataTable
填充Load()
。这样,错误应该在ExecuteReader()
方法中发生,并且应该是可捕获的。然后你不应该需要SqlDataAdapter
。
Try
'Create command
Dim command As New SqlCommand
command.CommandType = CommandType.StoredProcedure
conn = New SqlConnection(m_ConnectionString)
command.Connection = conn
command.CommandText = "trxInsertPartFromCOPICSPartFile"
With command.Parameters
.AddWithValue("@FileName", fileName)
End With
Dim dt As New DataTable
conn.Open()
Dim reader As SqlDataReader = command.ExecuteReader()
dt.Load(reader)
If dt.Rows.Count > 0 Then
Return dt
Else
Return Nothing
End If
Catch ex As SqlException
Dim myMessage As String = ex.Message
Finally
If conn.State <> ConnectionState.Closed Then
conn.Close()
End If
End Try
此外,如果将SELECT和INSERT组合到一个语句中,您可能会在几个级别上更好。您可以通过OUTPUT子句执行此操作,如下所示:
INSERT INTO Part
([PartNumber]
,[ReplacementPartNumber]
,[ShortDescription]
,[ListPrice]
,[PartStatusTypeID]
,[Weight]
,[CategoryID]
,[DateInserted]
,[SendToWebsite]
,[FileName]
,[MagentoPartTypeID]
,[PrintNumber])
OUTPUT INSERTED.[PartNumber] -- return the inserted values to the app code
SELECT
c.PartNumber
,c.ReplacementPartNumber
,c.ShortDescription
,c.ListPrice
,CASE WHEN c.PartStatusTypeID = @Enabled_PartStatusID
THEN @NotUploaded_PartStatusID
ELSE @Disabled_PartStatusID END
,@DefaultWeight
,@DefaultCategoryID
,@InsertionDate
,@SendToWebsite
,@FileName
,@MagentoPartTypeID
,c.PrintNumber
FROM
COPICSPartFile c
LEFT JOIN Part p on c.PartNumber = p.PartNumber
WHERE
p.PartNumber IS NULL