从TableAdapter获取@@ IDENTITY

时间:2010-09-13 21:02:10

标签: c# asp.net sql tableadapter

我正在努力完成一项看似简单的任务,该任务已经变成了几个小时的冒险:从@@Identity获取TableAdapter.Insert()

这是我的代码:

protected void submitBtn_Click(object sender, EventArgs e)
{
    AssetsDataSetTableAdapters.SitesTableAdapter sta = new AssetsDataSetTableAdapters.SitesTableAdapter();
    int insertedID = sta.Insert(siteTxt.Text,descTxt.Text);

    AssetsDataSetTableAdapters.NotesTableAdapter nta = new AssetsDataSetTableAdapters.NotesTableAdapter();
    nta.Insert(notesTxt.Text, insertedID, null,null,null,null,null,null);
    Response.Redirect("~/Default.aspx");
}

一个 answer 表示我可能需要做的就是更改ExecuteMode。我试过了。这使GetData()退出工作(因为我现在返回一个标量而不是rowdata)(我需要保留GetData())。它也没有解决这个问题,因为insertedID变量仍然设置为1。

我尝试在TableAdapter中创建第二个TypedDataSet.XSD并将该适配器的属性设置为“标量”,但它仍然失败,变量值为1.

生成的插入命令是

INSERT INTO [dbo].[Sites] ([Name], [Description]) VALUES (@Name, @Description);
SELECT Id, Name, Description FROM Sites WHERE (Id = SCOPE_IDENTITY())

并且“刷新数据表”(在Insert和Update语句之后添加select语句以检索Identity)也已设置。

环境

SQL Server 2008 R2,Visual Studio 2010,.NET 4,Windows XP,所有本地相同的计算机。

造成这种情况的原因是什么?

修改/更新

我想澄清我在Visual Studio中使用自动生成的代码。我不知道生成代码的“工具”是什么,但如果双击* .XSD文件,它会显示SQL表模式的UI和关联的TableAdapter。我想继续使用自动生成的代码,并以某种方式启用获取身份。我不想用存储过程手写这一切。

7 个答案:

答案 0 :(得分:8)

真正的答案:

  • 阅读以下注释!
  

从tableadapter插入函数中获取标识

     

我经常对此问题提出疑问,而且从未找到过   把它写下来的时间。

     

嗯,问题是如下:你有一个主键为int的表   类型定义为Identity,插入后需要知道PK值   新插行。完成此操作的步骤如下:

     

使用向导在中添加新的插入查询(让我们称之为InsertQuery)   查询体只是在底部添加SELECT SCOPE_IDENTITY()之后   保存此查询,更改此查询的ExecuteMode属性   代码中的NonQuery to Scalar写下面的内容(ta是TableAdapter   实例):

int id;

try
{
 id = Convert.toInt32(ta.InsertQuery(firstName, lastName, description));
}
catch (SQLException ex)
{
//...
}
finally
{
//...
}
     

用这个赚钱! :)由DraškoSarić于2009年3月12日发表。

     

自:   http://quickdeveloperstips.blogspot.nl/2009/03/get-identity-from-tableadapter-insert.html

备注:

  • 可以通过生成的插入查询的属性将 ExecutMode 设置为 Scalar 。 (按F4)。

  • 在我的版本(Visual Studio 2010 SP1)中,select语句是自动生成的。

答案 1 :(得分:4)

这是我的SQL代码。

CREATE PROCEDURE [dbo].[Branch_Insert]
(
    @UserId uniqueidentifier,
    @OrganisationId int,
    @InsertedID int OUTPUT
)
AS
    SET NOCOUNT OFF;
INSERT INTO [Branch] ([UserId], [OrganisationId]) 
VALUES (@UserId, @OrganisationId);

SELECT Id, UserId, OrganisationId FROM Branch WHERE (Id = SCOPE_IDENTITY())
SELECT @InsertedID = SCOPE_IDENTITY()

然后当我创建表适配器时 - 我可以立即看到@InsertedID参数。

然后从代码中,我所做的就是:

int? insertedId = 0;
branchTA.Insert(userId, orgId, ref insertedId);

我不是100%使用ref是最好的选择,但这对我有用。

祝你好运。

答案 2 :(得分:1)

所有信息都在这里,但我没有找到任何单一的答案,所以这是我使用的完整步骤。

添加插入查询,并向其添加SELECT SCOPE_IDENTITY(),如下所示:

INSERT INTO foo(bar) VALUES(@bar);
SELECT SCOPE_IDENTITY()

确保添加;到VS为你创建的INSERT语句的末尾。

完成添加查询向导后,请确保在设计视图中选择了查询,然后从属性窗格中将执行模式更改为Scalar

确保在从代码中调用查询时使用Convert.ToInt32(),如下所示:

id = Convert.ToInt32( dataTableAdapter.myInsertQuery("bar") )

如果没有Convert.ToInt32,您将不会遇到编译器错误,但是您将得到错误的返回值。

此外,每次修改查询时,都必须将执行模式重置为Scalar,因为VS每次都会将其更改回Non Query

答案 3 :(得分:1)

这是你如何做到的(在可视化设计器中)

  1. 右键单击表适配器和“添加查询”
  2. SQL语句 - 选择更新(最佳自动生成参数)
  3. 复制并粘贴您的SQL,它可以是多行的,只需确保“查询设计器”无法打开,因为它无法解释多个命令 - 我的示例显示了一个示例“merge”语句集(请注意,新的SERVERS具有Merge命令)。

    UPDATE YOURTABLE
    SET  YourTable_Column1 = @YourTable_Column1, YourTable_Column2 = @YourTableColumn2
    WHERE (YourTable_ID = @YourTable_ID)
    IF @@ROWCOUNT=0
      INSERT INTO YOURTABLE ([YourTable_Column1], [YourTable_Column2])
      VALUES (@YourTable_Column1, @YourTable_Column2)
    @YourTable_ID = SCOPE_IDENTITY()
    
  4. 从查询属性窗口/侧栏更改/添加@YourTable_ID参数。在参数集合编辑器中,ID参数需要具有InputOutput方向,以便在调用表适配器函数时更新该值。 (特别说明:确保您使InputOutput的任何列设计者没有将此列作为“只读”并且数据类型也匹配,否则更改数据表中的列或参数相应的信息)

  5. 这样可以节省为这种简单活动编写存储过程的需要。

    很哇。您会注意到,此方法是一种快速执行数据层功能的方法,而不必闯入SQL过程并编写大量的过程。唯一的问题是,你必须做很多跳舞......

答案 4 :(得分:0)

您需要设置插入以将标识作为输出值返回,然后将其作为适配器中的参数抓取。

这两个链接可以帮助您:

http://www.akadia.com/services/dotnet_autoincrement.html

http://msdn.microsoft.com/en-us/library/ks9f57t0.aspx

答案 5 :(得分:0)

您有两个选择:

  • 手动更改SQL代码
  • 使用Visual Studio生成的任何内容

我将使用以下SQL和ExecuteScalar。

INSERT INTO [dbo].[Sites] ([Name], [Description])
OUTPUT INSERTED.ID
VALUES (@Name, @Description);

答案 6 :(得分:-1)

一种方法是在insert命令后运行select查询。一个好方法是像这样包装原始命令:

    public int WrapInsert(Parameters)
    {
        .....
        int RowsAffected = this.Insert(..Parameters..);
        if ( RowsAffected > 0)
        {
            try
            {
                SqlCommand cm = this.Connection.CreateCommand();
                cm.CommandText = "SELECT @@IDENTITY";
                identity = Convert.ToInt32(cm.ExecuteScalar());
            }
            finally
            {
                ....
            }
        }
        return RowsAffected;
    }