Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Базы данных под .NET > Узнать ID при вставке в таблицу БД


Автор: MasterOfCode 13.8.2008, 09:40
Как при вставке в таблицу БД узнать сгенерированный ID поля?
Юзаю SQLCommand.

Автор: 1stain 13.8.2008, 11:01
Код

    string connectionString = @"Server=(local)\SQLEXPRESS; Database=Northwind; Trusted_Connection=yes";
    Int32 id = -1;
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        string sqlCommandText = @"INSERT INTO Categories (CategoryName, Description) Values(@CategoryNameParam, @DescriptionParam);
        SET @IdParam = CAST(SCOPE_IDENTITY() as INT);";
        SqlCommand command = new SqlCommand(sqlCommandText, connection);

        command.Parameters.AddWithValue("@CategoryNameParam", "Test category");
        command.Parameters.AddWithValue("@DescriptionParam", "Test category description");
        SqlParameter idParameter = command.Parameters.Add("@IdParam", System.Data.SqlDbType.Int);
        idParameter.Direction = System.Data.ParameterDirection.Output;

        try
        {
            if (connection.State != System.Data.ConnectionState.Open)
            {
                connection.Open();
            }
            command.ExecuteNonQuery();
            id = (Int32)idParameter.Value;
            Console.WriteLine("New category created successfully. Id = {0}", id);
        }
        catch
        {
            throw;
        }
    }

Автор: MasterOfCode 13.8.2008, 14:35
Спасибо!

Автор: vretsky 14.8.2008, 10:43
да только SCOPE_IDENTITY(), @@IDENTITY,IDENT_CURRENT()
не возвращают uniqueidentifier, очень жаль...

Автор: 1stain 14.8.2008, 13:30
vretsky, что мешает задать значение Id для uniqueidentifier прямо к коде, например в конструкторе класса и вставлять его в БД?
но если есть стремление к мазохизму, можно сделать так:
Код

string connectionString = @"Server=(local)\SQLEXPRESS; Database=Northwind; Trusted_Connection=yes";
            Guid id = Guid.Empty;
            using (SqlConnection connection = new SqlConnection(connectionString))
            {

                string sqlCommandText = @"IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Table_1]') AND type in (N'U'))
                                            DROP TABLE [dbo].[Table_1]

                                        CREATE TABLE [dbo].[Table_1](
                                        [ID] [uniqueidentifier] PRIMARY KEY,
                                        [NAME] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL);

                                        SET @IdParam = NEWID();
                                        INSERT INTO [Table_1] (
                                            [ID],
                                            [NAME]
                                        ) VALUES ( 
                                            @IdParam,
                                            @Name) ";
                SqlCommand command = new SqlCommand(sqlCommandText, connection);

                command.Parameters.AddWithValue("@Name", "Test name");
                SqlParameter idParameter = command.Parameters.Add("@IdParam", System.Data.SqlDbType.UniqueIdentifier);
                idParameter.Direction = System.Data.ParameterDirection.Output;

                try
                {
                    if (connection.State != System.Data.ConnectionState.Open)
                    {
                        connection.Open();
                    }
                    command.ExecuteNonQuery();
                    id = (Guid)idParameter.Value;
                    Console.WriteLine("New category created successfully. Id = {0}", id);
                }
                catch
                {
                    throw;
                }
            }

Автор: Idsa 14.8.2008, 17:25
1stain, думаю, если уж извращаться подобным образом, то нужно использовать не NewId, а NewSequantialId() (доступен с Sql Server 2005). Тогда индексы на базе Guid'ов будут практически равносильны индексам на базе int'ов.

Автор: vretsky 14.8.2008, 18:14
можно брать еще например из inserted

Добавлено через 59 секунд
 smile 

Автор: MasterOfCode 15.8.2008, 13:51
Цитата(1stain @ 13.8.2008,  11:01)
Код

    string connectionString = @"Server=(local)\SQLEXPRESS; Database=Northwind; Trusted_Connection=yes";
    Int32 id = -1;
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        string sqlCommandText = @"INSERT INTO Categories (CategoryName, Description) Values(@CategoryNameParam, @DescriptionParam);
        SET @IdParam = CAST(SCOPE_IDENTITY() as INT);";
        SqlCommand command = new SqlCommand(sqlCommandText, connection);

        command.Parameters.AddWithValue("@CategoryNameParam", "Test category");
        command.Parameters.AddWithValue("@DescriptionParam", "Test category description");
        SqlParameter idParameter = command.Parameters.Add("@IdParam", System.Data.SqlDbType.Int);
        idParameter.Direction = System.Data.ParameterDirection.Output;

        try
        {
            if (connection.State != System.Data.ConnectionState.Open)
            {
                connection.Open();
            }
            command.ExecuteNonQuery();
            id = (Int32)idParameter.Value;
            Console.WriteLine("New category created successfully. Id = {0}", id);
        }
        catch
        {
            throw;
        }
    }

не сработал че то. Выдал ошибку:
The variable name '@IdParam' has already been declared. Variable names must be unique within a query batch or stored procedure.
че то я не чего не понимаю... Где я ее объявлял, не пойму...

Добавлено через 1 минуту и 50 секунд
Сорри....  smile 
не брать во внимание предидущее сообщение.

Автор: jorikdima 10.1.2009, 19:53
Назрел вопрос по этой теме.
И все же... наверное многие используют autoincrement поля для идентификаторов. И вот если представить ситуацию, что в отсоединенном DataSet в какой то из таблиц добавилось несколько строк данных, или даже одна. Я вызываю метод Update адаптера (использую типизированные адаптеры и DataSet сгенеренные студией.. но думаю непринципиально), который в свою очередь вызывает команды INSERT СУБД. INSERT благополучно проходит, сколько то строк обновляется, но в отсоединенном DataSet никаких изменений поля автоинкремента не происходит. По идее только СУБД знает какое оно для каждой из строк. 
И как в таком случае мне обновить поля автоинкремента для отсоединенной сущности (DataSet или DataTable)? Вычитать только те строки которые я вставил??? Но как я вычитаю именно их? Уникального идентификатора то я их не знаю. Вычитать все из БД? Но это бред ибо ради обновления 2-3 строк вычитывать 1000 не хочется. Как быть?

Автор: jorikdima 12.1.2009, 10:00
Что-то тут вымер форум...

Автор: 1stain 12.1.2009, 21:45
jorikdima, как ни прискорбно, но придется поработать руками:
создаешь хранимую процедуру с OUTPUT параметром ID как описано выше, ставишь ее для InsertCommand в TableAdapter, руками прописываешь параметры и т.д. вобщем смотри аттачмент

Автор: jorikdima 13.1.2009, 09:51
Цитата(1stain @ 12.1.2009,  21:45)
jorikdima, как ни прискорбно, но придется поработать руками:
создаешь хранимую процедуру с OUTPUT параметром ID как описано выше, ставишь ее для InsertCommand в TableAdapter, руками прописываешь параметры и т.д. вобщем смотри аттачмент

Спасибо за ответ! Но хранимая процедура не катит, у меня MSSQL Compact Edition а там их нету :(
ОК ну тогда буду обновлять базу каждый раз smile она у меня не большая.

Автор: 1stain 13.1.2009, 12:24
Цитата(jorikdima @  13.1.2009,  09:51 Найти цитируемый пост)
хранимая процедура не катит


Меняешь тип InsertCommand у TableAdapter'a на Text, в конструктор формы пишешь
Код

string sqlString = @"INSERT INTO [Categories] (
                                    [CategoryName],
                                    [Description],
                                    [Picture]
                                ) VALUES ( 
                                    @CategoryName,
                                    @Description,
                                    @Picture );
                                 
                                SELECT @CategoryID = CAST(SCOPE_IDENTITY() AS INT);";
            categoriesTableAdapter.Adapter.InsertCommand.CommandText = sqlString;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)