Using Locate method when fetchAll=false

Discussion of open issues, suggestions and bugs regarding SDAC (SQL Server Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
FILLrate
Posts: 19
Joined: Thu 28 Jan 2010 09:14

Using Locate method when fetchAll=false

Post by FILLrate » Fri 02 Mar 2012 12:32

Hello.
It is Required to search the dataset record by unique field (TGuidField type) when FetchAll mode is false;
But according to the description, first calling Locate negates all the advantages of the "fetchall=false".
When the FetchAll property is False, the first call to the TMemDataSet.Locate and TMemDataSet.LocateEx methods may take a lot of time to retrieve additional records to the client side. The default value is True.
This is not acceptable. I tried to write my own decision based on code of Locate method.
Here's:

Code: Select all

type
  TMSQueryProtect = class(TMSQuery);

function LocateFetched(Query : TMSQuery; KeyField : string; Value : Variant): boolean;
var
  CurrentRecNumber : Integer;
  RecBuf: IntPtr;
  i : Integer;
  FieldOffset : Integer;
  ptr :  Pointer;
begin
  Result := False;
  with TMSQueryProtect(Query).Data do
  if RecordCount>0 then
    begin
      Result := False;
      CurrentRecNumber := RecordNo;
      RecordNo := 1;
      RecBuf := AllocRecBuf(RecBuf);
      try
        FieldOffset := FieldByName(KeyField).Offset;
        for I := 1 to RecordCount do
          begin
            GetRecord(RecBuf);
            if Marshal.PtrToStringUni(Marshal.ReadIntPtr(PtrOffset(RecBuf, FieldOffset)))=Value then
              begin
                Query.Resync([rmExact, rmCenter]);
                Result := true;
                Break;
              end;
            RecordNo:= RecordNo+1;
          end;
        if not Result then
          RecordNo := CurrentRecNumber;
      finally
        FreeRecBuf(RecBuf);
      end;
    end;
end;
Everething is ok in test application (only 1 form, 1 connect, 1 dataset), but in real app - Access violation (Marshal.PtrToStringUni).

:oops:

May be you can help... thx

_______________________________________________
Delphi XE 15.0.3953.35171
SDac 6.0.2

AndreyZ

Post by AndreyZ » Fri 02 Mar 2012 15:21

Hello,

There is no possibility of using the Locate or LocateEx methods when not all records are fetched to a client. Without fetching all records, these methods cannot return correct results.

FILLrate
Posts: 19
Joined: Thu 28 Jan 2010 09:14

Post by FILLrate » Sun 04 Mar 2012 21:08

AndreyZ wrote:Hello,

There is no possibility of using the Locate or LocateEx methods when not all records are fetched to a client. Without fetching all records, these methods cannot return correct results.
I know that I can not use methods Locate and LocateEx. That's why I wrote my own method (it doesn't connect with locate at all, just use some similar code). It works in a simple test application without any problems (see my first post). But when I put this code into a real application, I had an exception :oops: . So I ask only about a little help to indicate the direction in which I should seek an answer, because I can't find solution myself, thx.

AndreyZ

Post by AndreyZ » Mon 05 Mar 2012 11:47

You should insert the following code:

Code: Select all

if (FieldByName(KeyField).DataType = dtExtWideString) and
  not GetNull(FieldByName(KeyField).FieldNo, RecBuf) and
  (Marshal.ReadIntPtr(PtrOffset(RecBuf, FieldOffset))  nil) then
before the line:

Code: Select all

if Marshal.PtrToStringUni(Marshal.ReadIntPtr(PtrOffset(RecBuf, FieldOffset)))=Value then

FILLrate
Posts: 19
Joined: Thu 28 Jan 2010 09:14

Post by FILLrate » Mon 05 Mar 2012 15:24

AndreyZ wrote:You should insert the following code:

Code: Select all

if (FieldByName(KeyField).DataType = dtExtWideString) and
  not GetNull(FieldByName(KeyField).FieldNo, RecBuf) and
  (Marshal.ReadIntPtr(PtrOffset(RecBuf, FieldOffset))  nil) then
before the line:

Code: Select all

if Marshal.PtrToStringUni(Marshal.ReadIntPtr(PtrOffset(RecBuf, FieldOffset)))=Value then
Thx, I tried it. Unfortunately, it didn't help.
I replaced

Code: Select all

FieldByName(KeyField).DataType = dtExtWideString
on

Code: Select all

FieldByName(KeyField).DataType = dtGuid
and got an an access violation..

FILLrate
Posts: 19
Joined: Thu 28 Jan 2010 09:14

Post by FILLrate » Tue 06 Mar 2012 08:46

:idea: :!:
I found solution using TMemData.CompareFieldValue myself.
Thx for your attention.
:-)

AndreyZ

Post by AndreyZ » Tue 06 Mar 2012 11:59

It's good to see that you've found a solution. If any other questions come up, please contact us.

Post Reply