Por que você está fazendo isso em várias declarações em primeiro lugar? Por que não:
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);
Agora você só precisa chamar um
ExecuteNonQuery() e seu aplicativo não precisa se preocupar com o realmente SCOPE_IDENTITY() valor gerado. (Você ainda pode recuperar SCOPE_IDENTITY() se você quiser, é claro, usando ExecuteScalar - mas como Nenad aponta corretamente, escolha um em vez de chamar os dois.) Como agora sabemos que há uma chave estrangeira explícita aqui, ainda podemos reduzir seu código C# para uma chamada, mesmo que não possamos usar o
OUTPUT cláusula. 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
Seria ainda mais limpo colocar isso em um procedimento armazenado.