I have an ASP.NET page written in VB.NET that gets the items into a GridView
by using a SELECT
statement with INNER JOIN
and also allo
ItemId = AddNewItemSQL.ExecuteScalar()
AddNewItemSQL.ExecuteNonQuery()
These two rows next to each other will execute the command twice. You should remove the second one - ExecuteNonQuery. This will have your data inserted twice in the Items
- two same rows but with different IDs.
Since you only retrieve ItemID from the first row, that one should be inserted in project_items
, but the other one that was last inserted in items will have no matching row.
Also - complete section from beginning of button click method up before Dim AddNewItemComm As String
- where you open and close DataReader and do nothing with it seems completely unnecessary.
Why are you doing this in multiple statements in the first place? Why not:
INSERT dbo.Items (item_name, item_cost, item_code)
OUTPUT inserted.ItemID, @ProjectID, @ItemQuantity
INTO dbo.project_items(item_id, project_id, item_quantity)
VALUES (@ItemName, @ItemCost, @ItemCode);
Now you only have to call one ExecuteNonQuery()
and your app doesn't have to care about the actually SCOPE_IDENTITY()
value generated. (You can still retrieve SCOPE_IDENTITY()
if you want, of course, using ExecuteScalar
- but as Nenad rightly points out, pick one instead of calling both.)
Since we now know that there is an explicit foreign key here, we can still reduce your C# code to one call even if we can't use the OUTPUT
clause.
DECLARE @i INT;
INSERT dbo.Items (item_name, item_cost, item_code)
SELECT @ItemName, @ItemCost, @ItemCode;
SELECT @i = SCOPE_IDENTITY();
INSERT dbo.project_items(item_id, project_id, item_quantity)
SELECT @i, @ProjectID, @ItemQuantity
SELECT @i; -- if necessary
Would be even cleaner to put this into a stored procedure.