Проверка введенных данных в БД при транзакции

Обсуждение возникших проблем, предложений и ошибок UniDAC компонентов
Ответить
Fastex
Сообщения: 5
Зарегистрирован: Ср 29 ноя 2017 19:10

Проверка введенных данных в БД при транзакции

Сообщение Fastex » Ср 29 ноя 2017 19:21

Здравствуйте!

Пишу на C++ Builder Embarcadero XE
Доступ к БД: UniDAC
БД: MySQL
Таблицы: InnoDB (поддерживает транзакции)

Задача: проверить введенные пользователем данные с формы. Проверить нужно на то заполнены ли обязательные поля или нет. Форм, таблиц, текстовых полей и т. д. очень много, поэтому думаю об универсальном решении.

Вот, что придумал: смотрю в Information_Schema (Columns) по именам полей их свойство IS_NULLABLE, затем смотрю введенное значение пользователем в это поле и смотрю, может ли оно быть Null или не может. Составляю список всех пустых обязательных полей и вывожу их пользователю в виде сообщения, чтоб именно их заполнил.

! На пользовательской форме используются компоненты ввода DB (DBEdit, DBComboBox и т.д.), которые подключены к нужным DataSource. Пользователь вводит данные, нажимает "Сохранить", срабатывает метод Post();

! Необходимо использовать транзакции при сохранении.

Пробовал таблицы MyISAM (не поддерживают транзакции)
Вот в, чем затык:
1. Непонятно, где хранятся данные кроме компонентов до метода Post();
Пробовал смотреть значения полей, пока открыт Insert(), но еще не сработал Post() - везде NULL, т.е. данных пока еще нет в DataSet.
2. Непонятно, какой запрос отправляется в БД (и отправляется ли вообще), если пользователь с формы вводит данные, а потом срабатывает Post()
3. Нашел предложение отключить RequiredFields у TUniQuery, отправить Post(), и посмотреть, что отправилось, но в этом случае не срабатывает RollBack() (т.к. MyISAM не поддерживает транзакции).
Вот пример:

Код: Выделить всё

procedure TForm1.UniQuery_personsBeforePost(DataSet: TDataSet);
begin
 
  If UniQuery_persons.FieldByName('family').IsNull Then  begin
  ShowMessage('Заполните поле "Фамилия"');
  abort;
  end;
  end;
4. Когда я переключился на InnoDB, то я тупо не могу выполнить Post(); пока транзакция активна.
вот что написано в у вас в документах:

Код: Выделить всё

if not UniConnection.InTransaction then
     UniConnection.StartTransaction;
   try
     // Do some actions with database. For example:
     UniSQL1.Execute;
     UniSQL2.Execute;
 
     // Commit the current transaction to reflect changes in database if no errors were raised
     UniConnection.Commit;
   except
     // Rollback all changes in database made after StartTransaction if an error was raised
     UniConnection.Rollback;
   end;
То есть в транзакции выполняются 2 запроса и потом Commit().

Вот мой код сохранения:

Код: Выделить всё

 if(!ConnectionModule->CertificationConnection->InTransaction)
        {
            ConnectionModule->CertificationConnection->StartTransaction();
            try
                {
                    TableInfo.Table->Post();
                    if(CheckNotNullable()) //Вызов функции проверки введенных полей
                        ConnectionModule->CertificationConnection->Commit();
                    else    
                        ConnectionModule->CertificationConnection->Rollback();
                }
            catch (...)
                {
                    ConnectionModule->CertificationConnection->Rollback();
                }
        }
Тут я ни Post() ни Execute() выполнить не могу, ругается на активную транзакцию, не понимаю, как это выполняется в примере у разработчика.

Вопросы:
1. Где хранятся данные введенные в компоненты, подключенные к БД до выполнения запроса?
2. Какой запрос отправляет TUniQuery к БД при методе Post() и отправляет ли вообще?
3. Как организовать транзакцию в моем случае, когда нет явного запроса, а данные введены в форму?
4. Какие есть еще идеи по моей задаче?

Заранее спасибо!

ViktorV
Devart Team
Сообщения: 199
Зарегистрирован: Чт 31 июл 2014 09:52

Re: Проверка введенных данных в БД при транзакции

Сообщение ViktorV » Чт 30 ноя 2017 15:50

1. Данные хранятся в памяти компонентов. Вы можете получить значение используя следующий код:

Код: Выделить всё

var
  Value: Variant;
...
  Value := DBEdit.Field.Value;
Для получения более полной информации о работе с Data Control компонентами, вы можете обратиться к документации Embarcadero.
2. Для получения текста SQL-запроса отправляемого на сервер, при вызове методе Post, вы можете использовать dbMonitor.
3. При вызове метода Post SQL-запрос будет автоматически сформирован. К сожалению мы не смогли воспроизвести проблему, связанную с транзакционной ошибкой. Поэтому, для исследования проблемы, пожалуйста, составьте и вышлите нам небольшой пример, демонстрирующий проблему с помощью: https://www.devart.com/company/contactform.html, включая скрипты для создания и заполнения объектов БД.
4. Для решения вашей задачи, вместо использования транзакций вам лучше использовать CachedUpdates режим.
Более подробную информацию о CachedUpdates режиме вы можете получить в MyDAC помощи: https://www.devart.com/mydac/docs/?deva ... pdates.htm

Fastex
Сообщения: 5
Зарегистрирован: Ср 29 ноя 2017 19:10

Re: Проверка введенных данных в БД при транзакции

Сообщение Fastex » Пн 04 дек 2017 01:34

Благодарю за быстрый ответ!
Вариант с CachedUpdates очень помог.
Спасибо!

ViktorV
Devart Team
Сообщения: 199
Зарегистрирован: Чт 31 июл 2014 09:52

Re: Проверка введенных данных в БД при транзакции

Сообщение ViktorV » Пн 04 дек 2017 10:06

Спасибо за интерес к нашим продуктам.
Обращайтесь к нам, если у Вас возникнут вопросы по нашим продуктам.

Ответить