Конференция "Corba" » VarArrayLock и VarArrayUnlock [Delphi, Windows]
 
  • yuray © (01.10.07 16:21) [0]
    На сервере COM есть функция, которая конвертирует значения результата выборки из TADOQuery в массив значений типа Variant.

    function GetQueryResult(Query: TADOQuery): OleVariant;
    var
     i, j: integer;
    begin
     if Query.Active then Query.Close;
     try
       Query.Open;
       Query.First;
       Result := VarArrayCreate([0, Query.FieldCount - 1, 0, Query.RecordCount-1], varVariant);
       while not Query.Eof do
       begin
         for j := 0 to Query.RecordCount - 1 do
         begin
           for i := 0 to Query.FieldCount - 1 do
             Result[i, j]:=Query.Fields[i].Value;
           Query.Next;
         end;
       end;
     finally
       Query.Close;
     end;
    end;

    Вопрос. Нужно ли, а если нужно, то как правильно использовать VarArrayLock и VarArrayUnlock в этой функции?
    Спасибо.
  • Сергей М. © (01.10.07 16:42) [1]

    > Нужно ли


    Не нужно.

    А в связи с чем возникло сомнение ?


    > Query.First;


    Это лишнее.


    > Query.RecordCount


    Почитай внимательно Note в справке к методу TADOCustomDataSet.RecordCount
  • yuray © (01.10.07 17:37) [2]
    > А в связи с чем возникло сомнение ?
    Прочитал о инициализации больших массивов с помощью функции VarArrayLock() и процедуры VarArrayUnlock()... вот и возникли сомнения.

    > Query.First;

    А что? При открытии Query мы всегда будем на 1 записи?

    >Почитай внимательно Note в справке к методу TADOCustomDataSet.RecordCount

    Читал... "Indicates the total number of records in the recordset..."
    "...Should ADO not be able to determine that actual number of rows, RecordCount will return a value of negative one (-1)." Тут немножко не ясно...
  • umbra © (01.10.07 18:14) [3]

    > "...Should ADO not be able to determine that actual number
    > of rows, RecordCount will return a value of negative one
    > (-1)."

    это значит, что нельзя быть уверенным, что это св-во содержит реальное количество записей. Лучше пользоваться с-вами Bof и Eof.
  • yuray © (01.10.07 20:48) [4]
    > umbra ©   (01.10.07 18:14) [3]

    Мне нужно количество записей для создания массива. Неужели самому считать?

    i:=0;
    while not Query.Eof do
    begin
     inc(i);
     Query.Next;
    end;

    ???
  • Сергей М. © (02.10.07 08:38) [5]

    > При открытии Query мы всегда будем на 1 записи?


    А куда мы денемся с подводной лодки ?)


    > Прочитал о инициализации больших массивов с помощью функции
    > VarArrayLock() и процедуры VarArrayUnlock()


    Для простых типов VarArrayLock() в целях инициализации может и помогла бы, но у тебя Variant.


    > Неужели самому считать?


    Сходи в конец НД (Last), затем вернись в начало (First), вот тогда только получишь более-менее достоверное (зависит от многих условий) значение RecordCount.
  • yuray © (02.10.07 09:57) [6]
    Один RecordCount убрал :). Действительно было лишнее.

    function GetQueryResult(Query: TADOQuery): OleVariant;
    var
     i, j: Integer;
    begin
     if Query.Active then Query.Close;
     try
       Query.Open;
       Result := VarArrayCreate([0, Query.FieldCount - 1, 0, Query.RecordCount-1], varVariant);
       j := 0;
       while not Query.Eof do
       begin
           for i := 0 to Query.FieldCount - 1 do
             Result[i, j]:=Query.Fields[i].Value;
           Query.Next;
           Inc(j);
       end;
     finally
       Query.Close;
     end;
    end;

    Как поступить с инициализацией массива?

    Query.Open;
    Query.Last;
    Query.First;

    И только тогда можно пользоваться RecordCount?...
  • Сергей М. © (02.10.07 10:30) [7]

    > только тогда можно пользоваться RecordCount?


    Да.

    А собссно зачем такие сложности ?

    Почему не использовать TDataSetProvider ?
    Он все сделает сам - получит весь НД из твоего TADOQuery, упакует его в массив и вернет этот массив через св-во Data.
  • yuray © (02.10.07 10:39) [8]
    > А собссно зачем такие сложности ?

    Дело в том, что по условию задания клиенты этого сервера приложений должны быть написаны на С#...
  • Сергей М. © (02.10.07 11:11) [9]
    Ну и что ?

    Св-во DataSetProvider.Data точно такой же массив, описанный OeVariant-типом, только внутренний формат специфичен.
  • yuray © (02.10.07 11:16) [10]
    > Для простых типов VarArrayLock() в целях инициализации может и помогла бы, но у тебя Variant.

    Тоесть, если у меня будет массив значений типа Integer, то тогда будет справедливо писать

    var
     i: Integer;
     A: OleVariant;
     P: PIntegerArray;
    begin
     A := VarArrayCreate([0, 10000], varInteger);
     P:=VarArrayLock(A);
     try
       for i := 0 to 10000 do
         P^[i] := SomeIntegerValue;
     finally
       VarArrayUnlock(A);
     end;
    end;
  • yuray © (02.10.07 11:22) [11]
    > Св-во DataSetProvider.Data точно такой же массив, описанный OeVariant-типом, только внутренний формат специфичен.

    А как я узнаю этот формат в С#? Это старая тема. Например,
    http://pda.delphimaster.net/?id=1185269441&n=8. Из Вашего
    поста <Сергей М. ©   (29.08.07 09:29) [23]> я понял, что только через свой VarArray необходимо передавать DataSet, чтобы С# мог принять его...
  • Сергей М. © (02.10.07 11:53) [12]

    > yuray ©   (02.10.07 11:16) [10]


    Иллюстрация :

     v: OleVariant;
     pb: PByteArray;
    ..
     v := VarArrayCreate([1, 4], varByte);
     pb := VarArrayLock(v);
     PInteger(p)^ := $04030201; //оптимизированный по производительности эквивалент четырех нижеследующих строк
    //  p[0] := 1;
    //  p[1] := 2;
    //  p[2] := 3;
    //  p[3] := 4;

     VarArrayUnlock(v);
     showmessage(inttostr(v[1]) + ' ' + inttostr(v[2]) + ' ' + inttostr(v[3]) + ' ' + inttostr(v[4]));




    > как я узнаю этот формат


    Например, проанализировав код метода TDataSetProvider.GetData
  • yuray © (02.10.07 12:04) [13]
    > Сергей М.

    Спасибо за ответы. Буду анализировать код метода TDataSetProvider.GetData...
 
Конференция "Corba" » VarArrayLock и VarArrayUnlock [Delphi, Windows]
Есть новые Нет новых   [134430   +2][b:0][p:0.001]