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

saupg
Вт 29 мар 2016 14:14
Форум: SQL Server Data Access Components
Тема: TMSServiceBroker перестал работать в составе службы Windows
Ответы: 7
Просмотры: 17686

Re: TMSServiceBroker перестал работать в составе службы Windows

Теперь наблюдаются проблемы со стабильностью.
1. Какое-то время служба работает нормально и обрабатывает сообщения, потом перестаёт (при этом сообщения из очереди брокера пропадают).
2. После запуска службы сообщения не обрабатываются (при этом сообщения из очереди брокера пропадают), но при помощи перезапуска службы сообщения вдруг начинают приниматься, но вскоре всё равно всё упирается в п.1.
Нет ли каких-либо идей на этот счёт?
saupg
Чт 03 мар 2016 13:07
Форум: SQL Server Data Access Components
Тема: TMSServiceBroker перестал работать в составе службы Windows
Ответы: 7
Просмотры: 17686

Re: TMSServiceBroker перестал работать в составе службы Windows

Подскажите пожалуйста, в каком событии (в какой момент) необходимо вызывать этот метод?
saupg
Ср 02 мар 2016 17:10
Форум: SQL Server Data Access Components
Тема: TMSServiceBroker перестал работать в составе службы Windows
Ответы: 7
Просмотры: 17686

Re: TMSServiceBroker перестал работать в составе службы Windows

Обновился до версии SDAC 7.2.10 в ожидании исправления обсуждаемой ситуации (в описании версии 7.2.9 увидел "Bug with using TMSServiceBroker in Windows service is fixed").

По факту - снова не работает. Подскажите, что нужно сделать, чтобы сообщения начали обрабатываться.

Есть подозрение, что метод StartAsyncEventProcessor в модуле CRThread.pas как-то с этим связан, не даром вы к нему добавили параметр "Force: Boolean". Только вот метод этот нигде не используется. В документации найти упоминания о нём не удалось. Мне нужно его вызывать при запуске windows-службы или что?
saupg
Пн 19 окт 2015 09:33
Форум: SQL Server Data Access Components
Тема: TMSServiceBroker перестал работать в составе службы Windows
Ответы: 7
Просмотры: 17686

TMSServiceBroker перестал работать в составе службы Windows

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

Пытаюсь перейти на SDAC версии 7.2.8 с версии 6.11.23. Использую Delphi XE6.

Существует служба Windows (TService), которая с помощью компоненты TMSServiceBroker отслеживает сообщения в очереди брокера, отправляемые туда по расписанию заданиями SQL-сервера.

При компиляции этой службы на SDAC v7 сообщения из очереди забираются, но их обработка не выполняется (событие MSServiceBrokerBeginConversation не вызывается).

Поизучал ваши исходники и выяснил, что перестал работать таймер, по которому обрабатывались полученные сообщения из очереди. TMSServiceBroker использует отдельный поток для обработки полученных сообщений - класс TCRThreadWrapper.

1. В методе TCRThreadWrapper.SetTimer таймер теперь активируется только при условии выполнения в главном потоке (используется функция IsMainThread)! В случае службы Windows таймер не запускается никогда:

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

procedure TCRThreadWrapper.SetTimer;
const
  USER_TIMER_MINIMUM = $A;
begin
  if FTimer = nil then begin
    FTimer := TCRTimer.Create(nil);
    FTimer.Enabled := False;
    FTimer.Interval := USER_TIMER_MINIMUM;
    FTimer.OnTimer := DoTimer;
  end;

  Assert(not FTimer.Enabled);
  if IsMainThread then
    FTimer.Enabled := True;
end;
2. Собственно, метод SetTimer также не вызывается. В конструкторе используется та же проверка IsMainThread:

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

constructor TCRThreadWrapper.Create;
begin
  inherited Create;

  FLockState := {$IFDEF FPC}SyncObjs.{$ENDIF}TCriticalSection.Create;
  FThreadState := tsSuspended;
  FEvents := TThreadList.Create;
  FSendEventProcessed := TEvent.Create(nil, True, False, '');
  FThread := TCRThread.Create(Self);

  if IsMainThread then
    SetTimer
  else
    NeedToSetTimerList.Add(Self);
end;
Но список NeedToSetTimerList обрабатывается только в методе DoTimer, который вызывается по таймеру, создаваемому в методе SetTimer. Вот так круг замкнулся.

Помогите, пожалуйста. Как теперь использовать ваш компонент в службе Windows?
saupg
Ср 08 окт 2014 13:55
Форум: SQL Server Data Access Components
Тема: TMSScript и обобщённые табличные выражения
Ответы: 1
Просмотры: 4640

TMSScript и обобщённые табличные выражения

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

Часто в проекте использую рекурсивные запросы (обобщённые табличные выражения), в частности для выборки данных из иерархических справочников (записи с полями ID, ID_PARENT, NAME - каждая запись ссылается на родительскую запись, аналог - стуктура файловой системы с каталогами и файлами). Начиная с SQL Server 2005 такие запросы можно строить с помощью конструкции WITH (Common table expression или обобщённые табличные выражения). Но обязательно требуется наличие символа ";" перед этим ключевым словом (как правило, везде пишут так ";WITH ...", но можно оставлять ";" и в конце предыдущей строки).

Для выполнения скриптов в программе используется компонент TMSScript, который считает символ ";" разделителем, из-за чего пакет SQL-команд разбивается на "ДО WITH" и "ПОСЛЕ WITH". Если в пакете перед WITH декларируются локальные переменные, то в самом WITH и после него эти переменные уже не видимы. Очистка свойства Delimiter у TMSScript не помогает.

Пример простейшего скрипта с применением WITH, полностью валидного с точки зрения SQL сервера:

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

procedure TForm1.Button6Click(Sender: TObject);
begin
  MSScript2.SQL.Text := 'DECLARE @I SMALLINT ' +
    'SELECT @I = 1 ' +
    ';WITH TAB (M) AS ( ' +
    'SELECT @I ' +
    'UNION ALL ' +
    'SELECT CAST(T.M + 1 AS SMALLINT) ' +
    'FROM TAB T ' +
    'WHERE T.M < 10 ' +
    ') ' +
    'SELECT * FROM TAB ' +
    'GO';
  MSScript2.Execute;
end;
При выполнении получаем ошибку:
Неправильный синтаксис около конструкции ")".
Необходимо объявить скалярную переменную "@I".
При этом имеется такое наблюдение: если скрипт содержит ";WITH" в теле хранимой процедуры, то ";" игнорируется, и всё выполняется хорошо. Т.е. вы всё-таки производите какой-то анализ запроса, а не тупо разбиваете скрипт на выполняемые пакеты по символу ";".

Исправьте, пожалуйста.
saupg
Пн 14 июл 2014 08:47
Форум: SQL Server Data Access Components
Тема: TMSQuery.Options.DescribeParams и Integer Overflow
Ответы: 1
Просмотры: 4272

TMSQuery.Options.DescribeParams и Integer Overflow

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

В debug-сборке своего проекта я включаю опции "Runtime errors" компилятора (Overflow checking, Range checking).

Если в TMSQuery используется простейший SELECT-запрос без параметров (например, "select * from sys.objects"), и включено свойство Options.DescribeParams, то в модуле OLEDBAccess, в методе TOLEDBCommand.GetParameterInfo происходит "классическое" переполнение в вычислении границы цикла при использовании беззнакового типа:

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

var
  ...
  cParams: NativeUInt;
  ...
begin
  ...
  // cParams = 0, и вычитать из беззнакового числа ничего нельзя.
  for i := 0 to cParams - 1 do begin
  ...
end;
Исправьте, пожалуйста.
saupg
Чт 10 июл 2014 07:34
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

Хотелось бы уточнить ещё один момент: если я использую TMSQuеry только для получения данных, без необходимости редактирования (устанавливаю свойство ReadOnly := True), то нет никакого смысла в UniqueRecords = True? И для отключения лишних действий будет даже лучше отключать UniqueRecords для только читающих наборов данных (независимо от наличия конструкции WITH)?

Вообще странная ситуация с WITH. У меня редактируемые наборы данных с WITH (все, что я проверял) - работают нормально. А вот набор данных с WITH и ReadOnly = True, где никакого редактирования и не планировалось, приводит к ситуации из первого поста.
saupg
Пт 04 июл 2014 06:48
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

AndreyZ писал(а):Мы отвечали на этот вопрос: http://forums.devart.com/viewtopic.php?t=29501#p101103
Т.е. для этого случая, чтобы вернуть старое поведение новой версии SDAC необходимо установить опцию TMSQuery.Options.UniqueRecords в False.
Я оценил это как временное решение, а не постоянный костыль :(
К тому же были проблемы с UniqueRecords = False и вызовом метода Prepare.
Сейчас проблема с Prepare вроде бы отсутствует.

И тогда такой вопрос. Раз вы знаете в чём проблема, расскажите, пожалуйста, по каким критериям можно определить _не_возможность использования режима UniqueRecords = True?
В своей программе я наткнулся пока только на один проблемный запрос, но запросов в программе тысячи, есть довольно редко используемые и со сложными кейсами, на тестирование которых уйдёт уйма времени.
Или проще сразу всем Query проставить UniqueRecords = False, и в дальнейшей разработке для новых Query отключать этот режим? Зачем он тогда нужен по умолчанию, если его работа так непредсказуема?
saupg
Ср 02 июл 2014 06:41
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

AndreyZ писал(а):В версии SDAC версии 5.10.0.8 корректно работал скрипт, указанный вами в паралельном топике, или следующий скрипт:

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

MSScript.SQL.Text := 'SELECT (10'#10#13 +
  ' / '#10#13 +
  '2) AS RES';
MSScript.Execute;
Мы не можем изменить поведение, когда единственный символ '/' идет в начале строки, так как это повлечет изменения для множества наших пользователей.
Да, в реальных SQL-скриптах, как правило, используются отступы в коде. И получается перед "/" несколько пробелов. В таком случае, конечно, всё работает.
Не думал, что в этом будет какая-то принципиальная разница. Спасибо за уточнение.
saupg
Ср 02 июл 2014 06:16
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

По-прежнему ситуация такая же, как и в первом посте:
saupg писал(а): ...
Для этого запроса я получаю такое исключение: "Exception class EOLEDBError with message 'Ошибка протокола в потоке TDS'.".

Любое небольшое изменение текста запроса может как изменить поведение процесса, так и исправить ошибку.
Например, если в последней строке запроса изменить "LEFT JOIN" на "FULL JOIN", то получаем ошибку: "Exception class EOLEDBError with message 'Соединение больше нельзя использовать, так как ответ сервера на выполнявшуюся ранее инструкцию имел неправильный формат.'".

А если там же использовать "INNER JOIN", то ошибки нет. Так же ошибка пропадает при изменении таблицы, например, достаточно из первичного ключа исключить один из столбцов.
saupg
Вт 01 июл 2014 14:18
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

Эх, проверил и почистил всё ещё раз, полностью уверен что тестовый проект компилируется из исходников SDAC версии 6.10.20. Работаю с Delphi с 98-го года, все подлянки с dcu знаю.

Сравнил исходники 6.10.19 и 6.10.20.
Да, вижу сделанные вами изменения, например, в модуле DAScript.pas по поводу разделителя '/'. Вижу новую функцию SlashIsDelimiter и место её использования (547-ая строка), пошагово отлаживаю это место.

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

Ready := (FDelimiterState = dsSet) or (Code = lcEnd) or GetReady(Code);
if not Ready and (Code <> lcString) then begin
  Ready := CheckDelimeter and not IsSpecificSQL(StatementType);
  if not Ready and (FCurrDelimiter = FOwner.FDelimiter{';'}) and (FSt = '/') then begin
    if not SlashIsDelimiter then
      BlankLine := FParser.PrevCol = 0;
    if BlankLine then begin
      TempCode := FParser.GetNext(TempSt);
      if (TempCode = lcEnd) or
        (TempCode = lcBlank) and ((Pos(#13, TempSt) > 0) or (Pos(#10, TempSt) > 0))
      then
        Ready := True
      else
        FParser.Back;
    end;
  end;
end;
При встрече с символом '/' флаг BlankLine получается равным True, и затем TempCode равно lcBlank. В итоге флаг Ready получается True, и цикл разбора выражения прерывается, хотя в скрипте на следующей строке идёт продолжение (значение-делитель).
Тестовый скрипт всё тот же:

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

MSScript.SQL.Text := 'SELECT (10'#10#13 +
  '/'#10#13 +
  '2) AS RES';
MSScript.Execute;
Далее, не могу точно знать, куда смотреть в исходниках по поводу основной проблемы, изменений довольно много. В том фикс-билде, что вы передавали мне по почте, я вижу изменения в модуле DBAccess.pas (в функции TDADataSetService.GetDBKeyList). Но в билде 6.10.20 этих изменений почему-то нет... Хотя и фикс-билд на тестовом примере тоже даёт такие же ошибки.

Из всего вышесказанного я всё-таки делаю вывод, что по одному вопросу исправлено что-то не до конца, а по другому исправлено что-то не то. Прошу проверить работоспособность на предоставленных мной тестовых примерах.

Спасибо за терпение.
saupg
Пн 30 июн 2014 09:55
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

Так, вернёмся к нашей проблеме (отвлёкся на переход с Delphi XE на XE6 и адаптацию под 64 бита).
Обновился на билд SDAC 6.10.20. По факту - проблема из первого поста и проблема с символом "/" (из другой ветки) остались на месте. Судя по "revision history" эти изменения должны были попасть в сборку. Почистил все dcu, проверил пути и настройки тестового проекта. Ничего не работает :( Пробовал на Delphi XE и XE6.
Прошу проверить, попали ли все необходимые изменения в сборку 6.10.20?
saupg
Чт 08 май 2014 08:38
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

Да, что-то не везёт мне на примеры. Действительно, на 5-й версии пример из первого поста так же не работает, при этом свойство UniqueRecords на ситуацию никак не влияет.
Но, поверьте на слово, у меня реальные запросы в проекте, не работающие на 6-ой версии, прекрасно выполняются на 5-ой. Уж не знаю, в чём там отличие, но копать глубже нет времени.
Надесь, вы исправили именно эту ошибку :)

Кстати, на 5-ой версии при UniqueRecords := False не требуется обязательной подготовки запроса через вызов Prepare. Если вы говорите, что в 6-й версии так будет только при UniqueRecords := True, то мне обязательно нужен патч. Информация о лицензии приведена в первом посте. Пришлите исправление, пожалуйста.
saupg
Чт 08 май 2014 08:19
Форум: SQL Server Data Access Components
Тема: TMSScript и знак деления
Ответы: 3
Просмотры: 5278

Re: TMSScript и знак деления

Да, действительно, мой пример универсален, и даёт ошибку на любой версии.
Странно, но все мои скрипты создания хранимых процедур с таким же отдельно стоящим знаком деления выполняются нормально на старой версии, а на новой дают такую вот ошибку.

Кстати, в некоторых скриптах встречается, что знак деления стоит первым символом в строке, а за ним располагается делитель. И в каких-то случаях возникает такая же ошибка. Какой-либо закономерности я не вижу.

И ещё одно наблюдение - если текст скрипта вставить в компонент MSScript на форме, то всё хорошо. При загрузке того же скрипта из файла (MSScript.SQL.LoadFromFile) - получаем ошибку.

Немного поколдовал со своими скриптами и получилось родить один пример.

Сохраните скрипт в файл:

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

IF(EXISTS(SELECT 1 FROM sys.objects WHERE object_id=OBJECT_ID('spTest','P')))
DROP PROCEDURE dbo.spTest
GO 
CREATE PROCEDURE dbo.spTest
(
  @ID smallint,
  @ID_TEST smallint
)  
AS
BEGIN
  DECLARE @TEST SMALLINT
  SET @TEST=10
  ;WITH M(CNT) AS
  (
    SELECT @TEST
    UNION ALL
    SELECT CAST(CNT + 1 AS SMALLINT)
    FROM M
    WHERE M.CNT < @TEST
  )
  SELECT 
    COUNT(ID) AS CNT
  FROM M
  CROSS APPLY
  (
    SELECT 
      (10 
        / 
      2) AS ID
  ) A
END
Затем загружаем его в коде и пытаемся выполнить:

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

procedure TForm1.Button2Click(Sender: TObject);
var
  MSConnection: TMSConnection;
  MSScript: TMSScript;
begin
  MSConnection := TMSConnection.Create(Self);
  MSScript := TMSScript.Create(Self);
  try
    MSConnection.Authentication := auWindows;
    MSConnection.Server := 'db01';
    MSConnection.Database := 'master';
    MSConnection.LoginPrompt := False;

    MSScript.Connection := MSConnection;
    MSScript.SQL.LoadFromFile('D:\test.sql');

    MSScript.Execute;
  finally
    MSScript.Free;
    MSConnection.Free;
  end;
end;
На 6-ой версии в таком виде - не работает. Если текст скрипта поместить в компонент в дизайне, то работает. На 5-ой версии проблем никаких нет.

Да и собственно, речь идёт не о том, что в какой-то версии работает, а в какой-то нет. Мой пример наглядно продемонстрировал проблему - абсолютно валидный с точки зрения синтаксиса T-SQL скрипт не выполняется через ваш компонент.
Исправьте, пожалуйста.
saupg
Ср 07 май 2014 07:11
Форум: SQL Server Data Access Components
Тема: TMSQuery.Open портит память
Ответы: 17
Просмотры: 20758

Re: TMSQuery.Open портит память

Оказывается, если свойство UniqueRecords = False, то перед изменением данных в датасете надо обязательно вызывать метод Prepare (или устанавливать свойство Options.AutoPrepare := True, которое по-умолчанию = False). В документации про это ничего не сказано. Да и поведение какое-то нелогичное.

Пример кода для предыдущего проекта:

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

procedure TForm1.Button2Click(Sender: TObject);
const
  qTest = 'SELECT * FROM SDAC_BUG';
begin
  MSConnection1.Open;
  MSQuery1.Options.UniqueRecords := False;
  MSQuery1.SQL.Text := qTest;
  // MSQuery1.Prepare;
  MSQuery1.Open;
  MSQuery1.Insert; // <--- Exception
  MSConnection1.Close;
end;
С закомментаренной строкой MSQuery1.Prepare получаю ошибку "Exception class EDatabaseError with message 'MSQuery1: Cannot modify a read-only dataset'.".