3

我正在尝试完成一项看似简单的任务,却变成了几个小时的冒险:@@IdentityTableAdapter.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");
}

一个答案表明我可能需要做的就是更改ExecuteMode. 我试过了。这使得GetData()退出工作(因为我现在返回一个标量而不是行数据)(我需要保留 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语句以检索身份)。

环境

SQL Server 2008 R2、Visual Studio 2010、.NET 4、Windows XP,都是本地同一台机器。

这是什么原因造成的?

编辑/更新

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

4

7 回答 7

7

真正的答案:

  • 阅读下面的注释!

从 tableadapter 插入函数获取标识

我经常收到关于这个问题的问题,从来没有时间写下来。

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

使用向导在查询主体中添加新的插入查询(我们称之为 InsertQuery) 只需在保存此查询后在底部添加 SELECT SCOPE_IDENTITY() ,在您的代码中将此查询的 ExecuteMode 属性从 NonQuery 更改为 Scalar 编写以下内容(ta 是表适配器实例):

int id;

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

用这个赚钱!:) 由 Draško Sarić 于 2009 年 3 月 12 日发布

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

笔记:

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

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

于 2012-06-21T08:59:03.510 回答
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 是最好的选择,但这对我有用。

祝你好运。

于 2010-09-13T21:23:57.227 回答
3

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

添加一个插入查询,并附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,您不会得到编译器错误,但会得到错误的返回值。

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

于 2013-12-06T23:33:19.860 回答
1

这是你的做法(在视觉设计器中)

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

    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 参数。在 Parameter Collection Editor 中,ID 参数需要有一个 InputOutput 方向,以便在调用 Table Adapter 函数时更新该值。(特别注意:确保您输入输出的任何列,设计器都没有将此列设置为“只读”并且数据类型也匹配,否则更改数据表中的列,或相应的参数信息)

这应该可以省去为这样一个简单的活动编写存储过程的需要。

多哇。您会注意到,这种方法是一种执行数据层功能的快速方法,无需中断 SQL 过程并编写大量过程。唯一的问题,你必须跳很多舞......

于 2014-06-05T15:33:48.543 回答
0

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

这两个链接应该可以帮助您:

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

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

于 2010-09-13T21:11:14.387 回答
0

你有两个选择:

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

我会使用以下 SQL 和 ExecuteScalar。

INSERT INTO [dbo].[Sites] ([Name], [Description])
OUTPUT INSERTED.ID
VALUES (@Name, @Description);
于 2010-09-14T03:59:05.997 回答
-1

一种方法是在插入命令之后运行选择查询。一个好方法是像这样包装原始命令:

    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;
    }
于 2010-09-13T21:21:28.707 回答