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

У меня есть запрос на вставку строки в таблицу, в которой есть поле с именем ID, которое заполняется с помощью AUTO_INCREMENT в столбце. Мне нужно получить это значение для следующего бита функциональности, но когда я запускаю следующее, оно всегда возвращает 0, даже если фактическое значение не равно 0:

MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertInvoice;
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', " + bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID +  ")";
int id = Convert.ToInt32(comm.ExecuteScalar());

Насколько я понимаю, это должно вернуть столбец идентификатора, но каждый раз он просто возвращает 0. Любые идеи?

Обновлено:

Когда я бегу:

"INSERT INTO INVOICE (INVOICE_DATE, BOOK_FEE, ADMIN_FEE, TOTAL_FEE, CUSTOMER_ID) VALUES ('2009:01:01 10:21:12', 50, 7, 57, 2134);last_insert_id();"

Я получил:

{"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'last_insert_id()' at line 1"}

1. Можете ли вы опубликовать последний исполняемый CommandText? 2. Действительно ли вставляются записи?

Michael Haren 02.01.2009 06:20

Я разместил запрос, ошибку и да, строки вставляются.

Elie 02.01.2009 06:24

Хорошо, а как насчет "SELECT last_insert_id ();" в конце?

Michael Haren 02.01.2009 06:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
25
3
60 416
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

[Edit: добавлено "select" перед ссылками на last_insert_id ()]

А как насчет запуска "select last_insert_id();" после вставки?

MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertInvoice;
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', "  
    + bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID +  ");";
    + "select last_insert_id();"

int id = Convert.ToInt32(comm.ExecuteScalar());

Редактировать: Как упоминал Даффимо, вам действительно пригодятся параметризованные запросы как это.


Редактировать: Пока вы не переключитесь на параметризованную версию, вы можете найти мир со строкой.

comm.CommandText = string.Format("{0} '{1}', {2}, {3}, {4}, {5}); select last_insert_id();",
  insertInvoice, invoiceDate.ToString(...), bookFee, adminFee, totalFee, customerID);

Я бы попробовал запрос без него. Действительно ли вставляются записи?

Michael Haren 02.01.2009 06:10

Хорошо, а как насчет "SELECT last_insert_id ();" в конце?

Michael Haren 02.01.2009 06:26

Майкл: last_insert_id () не является потокобезопасным. Если другой поток вставляет что-то, last_insert_id вернет последний вставленный идентификатор при подключении к базе данных. Поэтому, если это делают несколько потоков (или даже отдельные процессы с одним и тем же пользователем для db), это будет ошибочным.

Ted 17.09.2013 17:31

Просто хотел отметить, что Тед прав, если отдельные потоки используют общее соединение. Если каждый поток устанавливает собственное соединение, он должен работать нормально, поскольку mysql обрабатывает его для каждого соединения. last_insert_id () документация

Pizano 10.10.2013 04:19

Меня беспокоит, что кто-то берет дату и хранит ее в базе данных как строку. Почему бы не сделать так, чтобы тип столбца отражал реальность?

Я также удивлен, увидев, что SQL-запрос строится с использованием конкатенации строк. Я разработчик Java и вообще не знаю C#, но мне было бы интересно, не было ли где-нибудь в библиотеке механизма привязки по строкам java.sql.PreparedStatement? Рекомендуется для защиты от атак с использованием SQL-инъекций. Еще одно преимущество - это возможное повышение производительности, поскольку SQL можно анализировать, проверять, один раз кэшировать и использовать повторно.

OP может использовать столбец даты в БД - мы не можем видеть эту часть. Я согласен с тем, что вам следует использовать параметризованные запросы. К счастью, это не похоже на то, что вы вставляете какой-либо текст, поэтому, строго говоря, вы, вероятно, в безопасности (хотя производительность может быть лучше).

Michael Haren 02.01.2009 05:57

Столбец на самом деле является датой, но если я попытаюсь вставить объект даты напрямую, у меня возникнут проблемы с его сбросом даты на набор нулей. Я новичок в C#, но я согласен с вами, вероятно, есть версия PreparedStatement для C#, и я изменю ее.

Elie 02.01.2009 05:59

Если столбец действительно является датой, что делает этот вызов «toString» с шаблоном форматирования в коде?

duffymo 02.01.2009 16:52

Также относительно привязки: Odbc имеет механизмы привязки для mysql, см. dev.mysql.com/doc/connector-odbc/en/… и stackoverflow.com/questions/18082840/…

sdjuan 26.10.2016 22:37

Фактически, метод ExecuteScalar возвращает первый столбец первой строки возвращаемого DataSet. В вашем случае вы делаете только Insert, вы на самом деле не запрашиваете какие-либо данные. Вам нужно запросить scope_identity () после вставки (это синтаксис SQL Server), и тогда вы получите свой ответ. Глянь сюда:

Связь

Обновлено: Как указал Майкл Харен, вы упомянули в своем теге, что используете MySql, используйте last_insert_id (); вместо scope_identity ();

Мой ответ включает версию scope_identity для Mysql в соответствии с тегами.

Michael Haren 02.01.2009 06:14

О, моя ошибка, я не заметил тег MySql. Отредактирую свой пост.

BFree 02.01.2009 06:16

Нет проблем - я сам достаточно часто скучаю по ним.

Michael Haren 02.01.2009 06:17

Используйте LastInsertedId.

Просмотрите мое предложение с примером здесь: http://livshitz.wordpress.com/2011/10/28/returning-last-inserted-id-in-c-using-mysql-db-provider/

MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertStatement;  // Set the insert statement
comm.ExecuteNonQuery();              // Execute the command
long id = comm.LastInsertedId;       // Get the ID of the inserted item
LastInsertedId не является потокобезопасным. Если другой поток вставляет что-то, LastInsertedId вернет последний вставленный идентификатор в соединении с базой данных. Поэтому, если это делают несколько потоков (или даже отдельные процессы с одним и тем же пользователем для db), это будет ошибочным.
Ted 17.09.2013 17:32

Потрясающе .. Я даже не думал о том, что MysqlData будет это предоставлять. Отлично.

Sami 11.03.2014 14:29

Возможно, cmd.LastInsertedId не является потокобезопасным ... но я предполагаю, что идентификатор извлекается в одном и том же вызове ExecuteNonQuery, а не в двух вызовах запроса, как в случае с SELECT LAST_INSERT_ID (). Возможно ли, что другой вызов из другого потока окажется «между» вставленной строкой и получением идентификатора. Я предполагаю, что сервер выполняет эту задачу и поэтому делает это немедленно. LAST_INSERT_ID потокобезопасен?

MrCalvin 28.01.2016 01:18

LastInsertedId возвращается немедленно с помощью cmd.executequery, поэтому я действительно не думаю, что другой поток может встать между этим. Но еще хотелось бы знать, чтобы быть уверенным на все 100%. Но по крайней мере мы знаем, что это безопасно от вставок других подключений

humudu 23.07.2018 16:44

Похоже, это безопасно. См .: stackoverflow.com/a/30959730/711863

mikeDOTexe 18.12.2019 07:32

Другие вопросы по теме