Найдено 217 результатов

Akella
Вт 09 июл 2019 08:11
Форум: Universal Data Access Components
Тема: Как правильно отключаться от базы и завершать работу приложения?
Ответы: 21
Просмотры: 30644

Как правильно отключаться от базы и завершать работу приложения?

У меня вот такая проблема иногда:
Project raised exception class EIBCError with message 'cannot disconnect database with open transactions (1 active)'
как и здесь:
https://forums.devart.com/viewtopic.php ... 63#p123863
Но закономерность не могу выяснить.

Т.е. получается, что на момент закрытия приложения есть одна (всегда одна) активная транзакция.
Если у компоненты-транзакции (TUniTransaction) есть свойство DefaultCloseAction, то оно должно работать.

Есть класс, в котором одно соединение TUniConnection и две транзакции TUniTransaction: одна читающая и одна пишущая.
Идея такая же, как у библиотеки FibPlus: читающая транзация постоянно открыта, а пишущая транзакция постоянно закрыта и открывается только на момент запись данных в базу, т.е. она максимально короткая.

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

procedure TObjectsSearch.InitDB;
begin
  connNotify := TUniConnection.Create(nil);
  InterBaseUniProvider1    := TInterBaseUniProvider.Create(connNotify);
  connNotify.ProviderName  := 'InterBase';
  connNotify.ConnectString := fConnectionString;
  connNotify.AutoCommit    := False;

  transW := TUniTransaction.Create(connNotify);
  transW.IsolationLevel     := ilCustom;
  transW.DefaultCloseAction := taRollback;
  transW.DefaultConnection  := connNotify;
  transW.SpecificOptions.Values['Params'] := 'write;nowait;rec_version;read_committed';

  transR := TUniTransaction.Create(connNotify);
  transR.IsolationLevel     := ilCustom;
  transR.DefaultCloseAction := taRollback;
  transR.DefaultConnection  := connNotify;
  transR.SpecificOptions.Values['Params'] := 'read;nowait;rec_version;read_committed';

  connNotify.DefaultTransaction := transR;

  connNotify.Connect;
деструктор класса

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

destructor TObjectsSearch.Destroy;
begin
  if Assigned(connNotify) then
  begin
    if connNotify.InTransaction then
      connNotify.Rollback;

    if connNotify.Connected then
      connNotify.Disconnect;

    connNotify.DisposeOf;
  end;

  inherited;
end;
ЧЯДНТ?
Спасибо.
Delphi Tokyo, Firebird 3, UniDAC 7.1.4.
Akella
Пт 05 июл 2019 11:50
Форум: Universal Data Access Components
Тема: UniStoredProc и пишущие транзакции в Firebird - как правильно?
Ответы: 1
Просмотры: 9007

UniStoredProc и пишущие транзакции в Firebird - как правильно?

Не пойму, как правильно указывать свойства для транзаций компоненты TUniStoredProc.
Есть несколько разных хранимок, т.е. есть только для чтения (селективные) и есть пишущие хранимки.

для создания UniStoredProc есть функция

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

// transR и transW - транзакции

//пишущая транзакция
  transW := TUniTransaction.Create(connNotify);
  transW.IsolationLevel := ilCustom;
  transW.DefaultConnection := connNotify;
  transW.SpecificOptions.Values['Params'] := 'write;nowait;rec_version;read_committed';

//читающая транзакция
  transR := TUniTransaction.Create(connNotify);
  transR.IsolationLevel := ilCustom;
  transR.DefaultConnection := connNotify;
  transR.SpecificOptions.Values['Params'] := 'read;nowait;rec_version;read_committed';
...
function CreateUniStoredProc(const name: string; isQuery: boolean = False): TUniStoredProc;
begin
  result := TUniStoredProc.Create(connNotify);
  result.Connection := connNotify;
  result.StoredProcName := name;
  result.Transaction := transR;
  result.UpdateTransaction := transW;
  result.PrepareSQL(isQuery);// False = not Query
end;
создаю TUniStoredProc:

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

// процедура осуществляет только чтение данных из БД
SP_GET_PARENT_REGION_DETAIL := CreateUniStoredProc('SP_GET_PARENT_REGION_DETAIL');

// процедура осуществляет чтение и запись
SP_TTELEGRAMMAILINGPARAM_INSPAR := CreateUniStoredProc('SP_TTELEGRAMMAILINGPARAM_INSPAR');
Внутри процедуры "SP_TTELEGRAMMAILINGPARAM_INSPAR" есть SQL-операторы Select и Insert.

Проблема в том, что на строке

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

SP_TTELEGRAMMAILINGPARAM_INSPAR.ExecSQL;
появляется ошибка, что выполняется запись данных в читающей транзакции:
Project raised exception class EIBCError with message 'attempted update during read-only transaction
At procedure 'SP_TTELEGRAMMAILINGPARAM_INSPAR' line: 12, col: 3'.
Так вот. Может вместо ExecSQL нужно какой-то другой метод дёргать, который затронет именно SP_TTELEGRAMMAILINGPARAM_INSPAR.UpdateTransaction?

Или же всё-таки придётся указывать в свойстве SP_TTELEGRAMMAILINGPARAM_INSPAR.Transaction пишущую транзакцию?
Как правильно?

Firebird 3
Delphi Tokyo
UniDAC 7.1.4
Akella
Чт 02 май 2019 14:16
Форум: Universal Data Access Components
Тема: получить значение выходного параметра (select xxx from proc в TUniStoredProc)
Ответы: 15
Просмотры: 16307

Re: получить значение выходного параметра (select xxx from proc в TUniStoredProc)

В продолжение теме.
На могу понять и в справке найти.

UniStoredProc.RecordCount возвращает 0, хотя в результате должно быть 10 записей.

Вижу, что IBExpert возвращает данные в виде 10ти записей.
Что нужно, чтобы в цикле обратиться ко всем записям UniStoredProc у селективной процедуры?
Спасибо.
Akella
Пт 26 апр 2019 12:58
Форум: Universal Data Access Components
Тема: получить значение выходного параметра (select xxx from proc в TUniStoredProc)
Ответы: 15
Просмотры: 16307

Re: получить значение выходного параметра (select xxx from proc в TUniStoredProc)

Точно, у меня же раньше так и было: ExecProc и ParamByName.
Теперь всё работает.
Akella
Пт 26 апр 2019 12:15
Форум: Universal Data Access Components
Тема: получить значение выходного параметра (select xxx from proc в TUniStoredProc)
Ответы: 15
Просмотры: 16307

Re: получить значение выходного параметра (select xxx from proc в TUniStoredProc)

Точно, у меня же раньше так и было: ExecProc и ParamByName.
Теперь всё работает.
Akella
Пт 26 апр 2019 09:12
Форум: Universal Data Access Components
Тема: получить значение выходного параметра (select xxx from proc в TUniStoredProc)
Ответы: 15
Просмотры: 16307

Re: получить значение выходного параметра (select xxx from proc в TUniStoredProc)

Теперь ошибка
Project exe raised exception class Exception with message 'SQL statement doesn't return rows'.

вот полный код

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

function TDM.GetContacts(id_obj, supertype: integer; id_telegram: Int64): string;
begin
  SP_GET_CONTACTS.StoredProcName := 'SP_GET_CONTACTS';
  SP_GET_CONTACTS.Prepare;
//  SP_GET_CONTACTS.SQL.Text := 'SELECT RES FROM SP_GET_CONTACTS(:ID_USER_VAR, :ID_OBJ_VAR, :ST_VAR, :ID_TELEGRAM_VAR)';
//  SP_GET_CONTACTS.PrepareSQL;
  SP_GET_CONTACTS.Params[0].Clear;
  SP_GET_CONTACTS.Params[1].AsInteger := id_obj;
  SP_GET_CONTACTS.Params[2].AsInteger := supertype;
  SP_GET_CONTACTS.Params[3].AsLargeInt := id_telegram;

  try
    //if not SP_GET_CONTACTS.Transaction.Active then SP_GET_CONTACTS.Transaction.StartTransaction;
    SP_GET_CONTACTS.Open;
    result := SP_GET_CONTACTS.FieldByName('RES').AsString;

  finally
    SP_GET_CONTACTS.Close;
  end;
end;
ошибка на строке
SP_GET_CONTACTS.Open;
Akella
Ср 24 апр 2019 14:36
Форум: Universal Data Access Components
Тема: получить значение выходного параметра (select xxx from proc в TUniStoredProc)
Ответы: 15
Просмотры: 16307

Re: получить значение выходного параметра (select xxx from proc в TUniStoredProc)

На всякий случай, добавлю кусок кода SP_GET_CONTACTS

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

create or alter procedure SP_GET_CONTACTS (
    ID_USER_VAR type of column USERS.ID,
    ID_OBJ_VAR type of column APART.ID,
    ST_VAR type of column TYPES.SUPERTYPE,
    ID_TELEGRAM_VAR type of column TTELEGRAMUSERS.TELEGRAM_ID)
returns (
    RES varchar(128))
as
как видите, RES есть.
И в IDE IBExpert код выполняется без ошибок
Akella
Ср 24 апр 2019 13:59
Форум: Universal Data Access Components
Тема: получить значение выходного параметра (select xxx from proc в TUniStoredProc)
Ответы: 15
Просмотры: 16307

получить значение выходного параметра (select xxx from proc в TUniStoredProc)

При попытке получить значение параметра RES поле выполнения процедуры получаю исключение, что параметра RES нет.

SP_GET_CONTACTS - TUniStoredProc.
База Firebird 3, кодировка по умолчанию UTF-8.

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

  SP_GET_CONTACTS.StoredProcName := 'SP_GET_CONTACTS';
  SP_GET_CONTACTS.SQL.Text := 'SELECT RES FROM SP_GET_CONTACTS(:ID_USER_VAR, :ID_OBJ_VAR, :ST_VAR, :ID_TELEGRAM_VAR)';
  SP_GET_CONTACTS.PrepareSQL;
  SP_GET_CONTACTS.Params[0].Clear;
  SP_GET_CONTACTS.Params[1].AsInteger := id_obj;
  SP_GET_CONTACTS.Params[2].AsInteger := supertype;
  SP_GET_CONTACTS.Params[3].AsLargeInt := id_telegram;

  try
    SP_GET_CONTACTS.ExecProc;

//ошибка здесь
    result := SP_GET_CONTACTS.ParamByName('RES').AsString;

  finally
    SP_GET_CONTACTS.Close;
  end;
Если написать запрос "SELECT :RES FROM ...", т.е. с двоеточием, то ошибка "conversion error from string":
Project raised exception class EIBCError with message 'Dynamic SQL Error
SQL error code = -303
conversion error from string "
*Ответств. агент: 7770777*"'.
Delphi Tokyo.
В настройках подключения есть: Character Set=UTF8;Use Unicode=True
Akella
Ср 28 ноя 2018 14:10
Форум: Universal Data Access Components
Тема: Автогенерация InsertSQL, UpdateSQL
Ответы: 1
Просмотры: 5643

Автогенерация InsertSQL, UpdateSQL

Я знаю, что у TUniQuery есть возможность сгенерировать доп. запрос на основе SelectSQL.
Но это неочевидно, в справке нет. Нет готовых методов.
Приходится открывать предварительно сам запрос, что есть не совсем правильно.

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

        UniQuery1.Open;
        UniQuery1.SQLUpdate.Text := TDBAccessUtils.SQLGenerator(UniQuery1).GenerateSQL(TDAParamsInfo.Create(TDAParamInfo) , _stUpdate, true);
        UniQuery1.SQLRefresh.Text := TDBAccessUtils.SQLGenerator(UniQuery1).GenerateSQL(TDAParamsInfo.Create(TDAParamInfo) , _stRefresh, true);
да и без UniQuery1.Open вываливается AV :(

Было бы здорово, если бы было что-то вроде:
UniQuery1.GelerateAllSQLs.
UniQuery1.GelerateInsertSQL;
UniQuery1.GelerateUpdateSQL;
UniQuery1.GelerateDeleteSQL;
и т.д.
и без обязательного открытия набора данных.