Получение @@ IDENTITY от TableAdapter - PullRequest
3 голосов
/ 14 сентября 2010

Я пытаюсь выполнить, казалось бы, простую задачу, которая превратилась в приключение продолжительностью в несколько часов: получение @@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");
}

One ответ предлагает все, что мне, возможно, придется изменить ExecuteMode.Я попробовал это.Это заставляет GetData() перестать работать (потому что теперь я возвращаю скаляр вместо строк) (мне нужно сохранить GetData ()).Это также не решает проблему в том, что переменная insertID по-прежнему имеет значение 1.

Я попытался создать второй TableAdapter в TypedDataSet.XSD и установить для этого адаптера значение «scalar», нопо-прежнему происходит сбой, когда переменная получает значение 1.

Сгенерированная команда вставки:

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

И "Обновить таблицу данных" (добавляет оператор выбора после операторов вставки и обновлениядля получения удостоверения »также установлено.

Среда

SQL Server 2008 R2, Visual Studio 2010, .NET 4, Windows XP, все локальные на одном компьютере.

Что вызывает это?

РЕДАКТИРОВАТЬ / ОБНОВИТЬ

Я хочу уточнить, что я использую автоматически сгенерированный код в Visual Studio. Я не знаючто такое «инструмент», сгенерировавший код, но если дважды щелкнуть файл * .XSD, он отображает пользовательский интерфейс схемы таблиц SQL и связанных с ним адаптеров таблиц. Я хочу продолжать использовать автоматически сгенерированный код и каким-то образом включить получение идентификатораЯ надеваюне хочу писать все это вручную с помощью хранимых процедур.

Ответы [ 7 ]

8 голосов
/ 21 июня 2012

Реальный ответ:

  • Читайте примечания ниже!

Получить удостоверение личности с помощью функции вставки в табличный адаптер

Я часто получаю вопросы об этой проблеме и не удосужился написать ее.

Что ж, проблема в следующем: у вас есть таблица с первичным ключом с типом int, определенным как Identity, и после вставки вам необходимо знать значение PK для вновь вставленной строки.Для этого необходимо выполнить следующие шаги:

использовать мастер для добавления нового запроса вставки (назовем его InsertQuery) в тело запроса, просто добавив SELECT SCOPE_IDENTITY () внизу после сохранения этого запроса, измените свойство ExecuteModeэтого запроса от NonQuery к Scalar в вашем коде напишите следующее (например, это экземпляр TableAdapter):

int id;

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

Зарабатывайте на этом!:) Опубликовано 12 марта 2009 г. Драшко Саричем

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

Примечания:

  • Настройка ExecutMode до Scalar возможно через Свойства вашего сгенерированного запроса на вставку.(нажмите F4).

  • В моей версии (Visual Studio 2010 SP1) оператор выбора был создан автоматически.

4 голосов
/ 14 сентября 2010

Вот мой 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()

Затем, когда я создаю Table Adapter - я могу сразу увидеть параметр @InsertedID.

Затем из кода все, что я делаю, это:

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

Я не уверен на 100%, является ли использование ref лучшим вариантом, но это работает для меня.

Удачи.

1 голос
/ 05 июня 2014

Вот как вы это делаете (в визуальном конструкторе)

  1. Щелкните правой кнопкой мыши адаптер таблицы и выберите «Добавить запрос»
  2. Операторы SQL - Выберите Обновить (лучшие параметры авто-генерации)
  3. Скопируйте и вставьте свой SQL, он может быть многострочным, просто убедитесь, что «Конструктор запросов» не открывается , так как он не сможет интерпретировать несколько команды - в моем примере показан пример набора операторов «слияния» (обратите внимание, что у новых SERVERS есть команды слияния).

    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, у конструктора нет этого столбца как «Только для чтения» и что типы данных также совпадают, в противном случае измените столбец в datatable или параметр информация соответственно)

Это должно избавить от необходимости написания хранимой процедуры для такого простого действия.

Много вау. Вы заметите, что этот метод является быстрым способом выполнения функций уровня данных без необходимости разбивать процедуры SQL и писать тонну процедур. Единственная проблема, вам нужно много танцевать ...

1 голос
/ 07 декабря 2013

Вся информация здесь, но я не нашел ни одного полного ответа, поэтому вот полные шаги, которые я использую.

Добавьте запрос вставки и добавьте к нему SELECT SCOPE_IDENTITY(), например:

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

Убедитесь, что вы добавили; до конца инструкции INSERT, которую VS создает для вас.

После завершения работы мастера добавления запросов убедитесь, что запрос выбран в представлении конструктора, затем измените режим выполнения на Scalar на панели свойств.

Убедитесь, что вы используете Convert.ToInt32 () при вызове запроса из своего кода, например:

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

Вы не получите ошибок компилятора без Convert.ToInt32, но вы получите неправильное возвращаемое значение.

Кроме того, каждый раз, когда вы изменяете запрос, вы должны сбросить режим выполнения обратно на Scalar, потому что VS будет каждый раз возвращать его на Non Query.

0 голосов
/ 14 сентября 2010

У вас есть ровно два варианта:

  • изменить код SQL вручную
  • используйте все, что генерирует Visual Studio

Я бы использовал следующий SQL и ExecuteScalar.

INSERT INTO [dbo].[Sites] ([Name], [Description])
OUTPUT INSERTED.ID
VALUES (@Name, @Description);
0 голосов
/ 14 сентября 2010

Один из способов - выполнить запрос на выбор после команды вставки.Хороший способ - обернуть оригинальную команду следующим образом:

    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;
    }
0 голосов
/ 14 сентября 2010

Вам потребуется настроить вставку так, чтобы она возвращала идентификатор в качестве выходного значения, а затем захватить его как параметр в вашем адаптере.

Эти две ссылки должны помочь вам:

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

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

...