Jump to content

ertank

Members
  • Content Count

    231
  • Joined

  • Last visited

Posts posted by ertank


  1. I am using UniDAC and there is TUniConnection.Options.KeepDesignConnected parameter. I expect MyDAC to have a similar parameter.

     

    On 2/29/2024 at 2:31 PM, dormky said:

    And yes, I did add it in the database. And I only have one database.

    I didn't understand why this is a problem since you have a single database and necessary columns added in it.


  2. I don't use MySQL. But,

    I would use same letter case as the table column name.

    I would double check that design-time and run-time actually uses the same server, database, table

     

    Edit: Reading your problem again, it feels you added a column in TMyTable but not in your database table.


  3. I am not sure if below approach is suitable for you. 

    type
      FieldList = TArray<TField>;
      PFieldList = ^FieldList;
    
    procedure FindAllFields(DataSet: TDataSet; Fields: PFieldList; const FieldNames: TArray<string>; const RaiseExceptionForMissingFields: Boolean = True);
    var
      I: Integer;
    begin
      Assert(Length(Fields^) = Length(FieldNames), 'Fields count <> FieldNames count!');
    
      for I := Low(Fields^) to High(Fields^) do
      begin
        Fields^[I] := DataSet.FindField(FieldNames[I]);
        if (Fields^[I] = nil) and RaiseExceptionForMissingFields then
          raise Exception.Create('Missing field dataset "' + FieldNames[I] + '"');
      end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      LFieldList: FieldList;
    begin
      SetLength(LFieldList, 4);
      // Below will raise an exception because of the last empty field name and RaiseExceptionForMissingFields=True
      FindAllFields(VirtualTable1, @LFieldList, ['a', 'b', 'c', '']);
      //...
    end;

    This would require you to remember Indexes for your fieldnames. Not very convenient if you are to have a lot of fields and do different calculations or such with them.

     


  4. 4 hours ago, Hans♫ said:

    We have received reports from our Turkish users that our app is failing.

    As per documentation TStringHelper.ToUpper uses locale specific case conversion.

    As per documentation UpperCase or SameText uses 7-bit ASCII conversion. Only letters between 'a' and 'z' are converted to uppercase.

     

    Since you are using ToUpper, uppercase of 'This' in Turkish locale is 'THİS' (upper case I letter with dot at top). Moreover, lower case for 'THIS' in Turkish locale is 'thıs' (small caps i letter without dot at top).

     

    I cannot remember off my mind right now but there are other languages where some characters small and upper cases do not follow ASCII type of conversion.


  5. Even if I make it identical C# enum with Delphi enum, There is still one byte difference in total struct vs record comparison. I check even the last item offset in C# struct matches to Delphi and this last item size also matches on both C# and Delphi. It must be that C# has one byte more at the very bottom of its struct.

     

    @FPiette advise to add it at the end of Delphi record as a dummy variable and I can do that.

     

    I wonder if I absolutely need it?

    If I do need it, I wonder if there is another way of handling that in newer Delphi versions like a compiler directive {$MINENUMSIZE 4}?

     

    Thanks.


  6. I used x86 target on C# project and Delphi side is also 32bit application. Using your offset function revealed some differences. C# struct "Members" has following remarked offsets (Layout is indeed commented in the project code. I removed remark for testing and this didn't change total struct size)

    //[StructLayout(LayoutKind.Sequential)]
    public struct Members
    {
        public Tags ResponsedTag; // Offset 0
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string StartRNo; // Offset 4
        // continues and ends as following
        public GrupDF02 groupDF02;
        public GrupDF41 groupDF41;
        public GrupDF6F groupDF6F;
    }

    However, Delphi record has following offsets. I intentionally didn't use packed record as I am completely unsure of the C# side.

    TMembers = record 
      ResponsedTag: TTags; // Offset 0
    
      StartRNo: Array[0..31] of AnsiChar; // Offset 1
      // continues and ends as following
      groupDF02: TGrupDF02;
      groupDF41: TGrupDF41;
      groupDF6F: TGrupDF6F;  
    end;

    Tags is an enum and takes up 4 bytes in C# but 1 byte in Delphi. That explains 3 bytes difference. I'm not sure about the reason of this difference.

     

    These last three item's sizes on C# and Delphi are the same. When I compare the very last item "groupDF6F" offsets, the difference is still 3 bytes. So, I could not find a reason for total difference of 4 bytes.

     

    I don't know how I can modify Delphi to match C# just for this enum difference.

    I could not find where this remaining 1 byte difference is coming from.


  7. Hello,

     

    I need to convert a C# project into Delphi. This project is using a C++ DLL and passing a struct named Members to the DLL.

     

    I could not make same size record in Delphi. There is a 4 byte difference and Delphi is smaller.

     

    The Members struct has more than 80 string variables, one enum type and three other structs. These three other struct sizes are exactly match to Delphi conversions. They all have StructLayout as Sequential defined. But, Members struct has no StructLayout at all. Actually, it was defined as Sequential before but now that code is remarked. There are only MarshalAs for strings like below

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string StartRNo;

    I searched on the web and I think I should convert above to Delphi as following

    StartRNo: Array[0..31] of AnsiChar;

    This Delphi definition give me exact size for three other structs. They have only string variables.

     

    DLL function calls are CharSet.Ansi for all, but the only one using the Members struct is defined as CharSet.Unicode. If I am to use Char instead of AnsiChar on Delphi side for strings (just for the Members record), difference is a lot more like double.

     

    I am unable to figure why there is a 4 byte difference and how to make both C# Members struct and Delphi record identical.

     

    Any help is appreciated.

     

    Thanks & Regards,

    Ertan


  8. I do not know about Superobjects but Delphi standard json library can do following

    uses
      System.JSON,
      System.Generics.Collections;
    
    procedure TForm1.Button1Click(Sender: TObject);
    const
      JsonText = '{ "splash.annually": "normal" }';
    var
      Json: TJSONValue;
    begin
      Json := TJSONObject.ParseJSONValue(JsonText, False, False);
      if Json <> nil then
      begin
        if Json.FindValue('["splash.annually"]') <> nil then
        begin
          ShowMessage(Json.FindValue('["splash.annually"]').AsType<string>);
        end;
        Json.Free();
      end;
    end;

     


  9. On 7/1/2023 at 5:05 PM, PeterBelow said:

    If the units generated by the SOAP importer declare the interface types without a GUID just try to add one (Ctrl-Shift-G if I remember correctly, with caret on a new line after the one with the interface keyword).

    Yes, I now see that both web services are defined using the same GUID by WSDL importer. Their methods are different, things they do are different but both has identical name and GUIDs.

    image.png.9d218d54a9d9732a034837e468778d0c.png

     

    After manually changing one of them to use a different GUID everything worked just fine in a single project.

     

    Thank you.

     

    P.S. I already build two separate DLLs and released them. They are working OK. But this GUID is something I will check for the future.


  10. Hello,

     

    I am trying to figure out a way to use two Veriban SOAP web services in a single project. These web services both are named same as IIntegrationService in imported WSDL units.

     

    http://efaturatransfertest.veriban.com.tr/IntegrationService.svc?wsdl

    http://earsivtransfertest.veriban.com.tr/IntegrationService.svc?wsdl

     

    For anyone interested, Veriban publicly make it available test user and password. Same for both webservices above.

    Username: TESTER@VRBN

    Password: Vtest*2020*

     

    If I build two separate VCL applications each using one of these services WSDL imported unit, everything is fine and works. But, If I rename WSDL imported units like VeribanEInvoiceIntegrationService.pas and VeribanEArchiveInvoiceIntegrationService.pas and put these files in uses section of a single VCL project. Login method runs fine for both of them. But VeribanEArchiveInvoiceIntegrationService.pas one gives me access violation for below method. My final goal is to use these services both in a single Windows Service project which currently gets same AV exception. It did not help to have wrapper classes for each service in a separate unit.

     

    http://earsivtransfertest.veriban.com.tr/IntegrationService.svc method GetSalesInvoiceUUIDListWithCustomerWithDate

     

    I make sure that I refer to each unit interface when casting THTTPRIO as below
     

    var
      RIO: THTTPRIO;
      WS: VeribanEArchiveInvoiceIntegrationService.IIntegrationService;
      LResponse: VeribanEArchiveInvoiceIntegrationService.ArrayOfString;
    begin
    ...
      WS := (RIO as VeribanEArchiveInvoiceIntegrationService.IIntegrationService);
    ...
      LResponse := WS.GetSalesInvoiceUUIDListWithCustomerWithDate(FSessionCode, LStartDate, LEndDate);  // AV here

     

    My questions are:

    - Is there anything that I am missing which leads to AV?

    - Is it possible to use both of these services in a single project?

     

    Thanks & Regards,

    Ertan

     

    P.S. I attached AV call stack just in case.image_2023-06-28_174557687.thumb.png.27a239958086ca4dba2f2e2d5a8aea32.png


  11. Hello,

     

    I am using v8.71 of ICS. There is a device connecting to my application and sending some data. So, I basically wait for a connection and communicate with that device both ways.

    Occationally, TWSocketClient.OnDataAvailable event triggers even if there is no data ( aka GetRcvdCount = -1)

     

    I just wonder if this is normal and what might be possible reasons?

     

    Thanks & Regards,

    Ertan


  12. Hello,

     

    There are some chain requests triggered from clients. Some requests among them takes time processing on the server side. I should send a response to client fast. Server side operations are not relevant to the response.

     

    Since, MARS is handling each request in a separate thread, I also created a custom thread for this time consuming operation and process it. My problem is, database context is removed as soon as response is sent and its thread is destroyed. Any further database operations from that point in my custom thread results in access violation.

     

    Is there a way that I can get a database connection from MARS database pool for my own custom threads independent of requests?

     

    Thanks & Regards,

    Ertan


  13. Hi,

     

    I didn't know about HeaderParam attribute.

        [POST, Path('test')]
        function Test([HeaderParam('x-api-key')] const ApiKey: string;
                      [BodyParam] const Body: string): string;

    Using above, I can check about ApiKey value in the function and use EMARSHttpException for returning a 404 error if necessary.

     

    I was searching a way to block a request with wrong x-api-key header value even before function code execution, but above approach is a solution, too.

     

    Thanks & Regards,

    Ertan


  14. Hi,

     

    If possible, I do not want to use existing "Authorization" header. I would like to allow access or block access depending on "x-api-key" header on each request.

     

    - x-api-key header missing: Block the request using 404

    - x-api-key header exists: Check in a method that it is correct. Allow only if correct, else block the request using 404

     

    Very basic example would be:

    Incoming request Header:
    x-api-key: my_own_key_data
    
    Incoming request Body:
    {"data":"Various json data. To be read as whole in a string"}

     

    Attached you can find is a sample postman request.

     

    Thanks & Regards,

    Ertan

    webhook_test.postman_collection.json

×