2015-10-20 38 views
0

我正在处理遗留项目,需要插入一行并返回该行或其标识。返回使用sql存储过程插入的行的标识

新行以正确的值插入,只有在返回到.net时,数据集中才会返回任何内容。

我试过选择@@identity,RETURN,OUTPUT,但我试过的一切数据集都是空的(但不是空的)。

这不是MyUtils.DBHelper.GetDataSet的错,因为它在其他地方使用并执行并返回正常。

USE [dbname] 
GO 

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER Procedure [dbo].[DuplicateOrder] 
(
    @sourceid int, 
    @var1 int, 
    @var2 decimal(10,2), 
) 
AS 

INSERT INTO OrderHeader (
    Users_ID, 
    Stores_ID, 
    ) 
SELECT 
    @var1, 
    @var2 
FROM Order 
WHERE id = @sourceid 
GO 

我使用执行存储过程的代码是:

Using cmd As New SqlCommand("DuplicateOrder") With {.CommandType = CommandType.StoredProcedure} 
        cmd.Parameters.AddWithValue("@sourceid", sourceId) 
        cmd.Parameters.AddWithValue("@var1 ", var1) 
        cmd.Parameters.AddWithValue("@var2 ", var2) 
        ds = MyUtils.DBHelper.GetDataSet(cmd) 
End Using 
+0

如何你有没有试过选择@@身份?除非您处于多连接环境中,否则这通常很适用 – Grantly

回答

1

这应该是关键:

ALTER Procedure [dbo].[DuplicateOrder] 
(
    @sourceid int, 
    @var1 int, 
    @var2 decimal(10,2) 
) 
AS 

INSERT INTO OrderHeader (
    Users_ID, 
    Stores_ID 
    ) 
SELECT 
    @var1, 
    @var2 

SELECT @@IDENTITY AS ident 
GO 

我测试了它o n SQL服务器,它返回一行,列ident

0

你试图执行此SELECT IDENT_CURRENT ('Table') AS Current_Identity;应该在当前会话中返回最后生成的标识和范围

0

@@身份和返回将无法正常工作(SCOPE_IDENT(),IDENT_CURRENT()以及如果您打算一次插入多个行将无法正常工作)。

最好的办法是使用OUTPUT,但在代码中看不到任何OUTPUT。下面是一个例子(代码部分是用C#编写的,但你可以很容易地转换它,比如使用Telerik转换器或者自己编写 - 有N种方法可以传递数据,我在本例中选择了XML):

SQL代码生成的示例表和过程:

USE [Test]; 
GO 

CREATE TABLE IdentityTest 
    (
    Id INT IDENTITY 
      NOT NULL 
      PRIMARY KEY , 
    FirstName VARCHAR(20) , 
    LastName VARCHAR(20) 
); 
GO 

CREATE PROCEDURE InsertTestData 
    (
    @XML VARCHAR(MAX) , 
    @NodeName VARCHAR(1000) 
) 
AS 
    BEGIN 

    DECLARE @myIDTable TABLE (theID INT); 

    DECLARE @hDoc INT; 
    DECLARE @tbl TABLE 
     (
     fName VARCHAR(20) , 
     lName VARCHAR(20) 
    ); 
    EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML; 
    INSERT @tbl 
    SELECT * 
    FROM OPENXML(@hDoc, @NodeName, 1) WITH (fName VARCHAR(20), lName VARCHAR(20)); 
    EXEC sp_xml_removedocument @hDoc; 

    INSERT INTO [IdentityTest] ([FirstName], [LastName]) 
    OUTPUT [Inserted].[Id] 
      INTO @myIDTable 
    SELECT t.[fName], t.[lName] 
    FROM @tbl AS t; 

    SELECT * 
    FROM @myIDTable AS [mit]; 

    END; 
GO 

这是用SP和插入多行和找回自己的ID的C#代码(可能已经返回了全行数据):

void Main() 
{ 
    List<Person> people = new List<Person> { 
    new Person { FName = "Sam", LName="Jones"}, 
    new Person { FName = "Cetin", LName="Basoz"}, 
    new Person { FName = "John", LName="Doe"}, 
    new Person { FName = "Steven", LName="Smith"}, 
    new Person { FName = "Bob", LName="Carpenter"}, 
    }; 

    for (int i = 0; i < 100; i++) 
    { 
    people.Add(new Person 
    { 
     FName = string.Format("FName#{0}", i), 
     LName = string.Format("LName#{0}", i) 
    }); 
    } 

    var peopleAsXML = new XElement("People", 
    from p in people 
    select new XElement("Person", 
     new XAttribute("fName", p.FName), 
     new XAttribute("lName", p.LName))); 

    string sql = @"InsertTestData"; 
    DataTable result = new DataTable(); 
    using (SqlConnection con = new SqlConnection(@"server=.\SQLExpress2012;Trusted_Connection=yes;Database=Test")) 
    { 
    SqlCommand cmd = new SqlCommand(sql, con); 
    cmd.CommandType = CommandType.StoredProcedure; 
    cmd.Parameters.AddWithValue("@XML", peopleAsXML.ToString()); 
    cmd.Parameters.AddWithValue("@NodeName", "/People/Person"); 
    con.Open(); 
    result.Load(cmd.ExecuteReader()); 
    con.Close(); 
    } 
    // check top 5 returned 
    for (int i = 0; i < 5; i++) 
    { 
    Console.WriteLine((int)result.Rows[i]["theID"]); 
    } 
} 

public class Person 
{ 
    public string FName { get; set; } 
    public string LName { get; set; } 
}