What's the best way to store a Delphi set in a dataset?

前端 未结 3 441
醉话见心
醉话见心 2021-02-06 12:29

The title pretty much says it all. I\'m using a TClientDataset to store an array of objects, and one of the objects has a member defined as a set of an enumerat

相关标签:
3条回答
  • 2021-02-06 12:37

    You can convert them to Byte, like this:

    var
      States : TUpdateStatusSet; // Can be any set, I took this one from DB.pas unit
      SetAsAInteger: Integer;
      dbs: Pointer; // Here's the trick
    begin
      States := [usModified, usInserted]; // Putting some content in that set
      dbs := @States;
      SetAsAInteger := PByte(dbs)^;
      //Once you got it, SetAsAInteger is just another ordinary integer variable.
      //Use it the way you like.
    end;
    

    To recover from anywhere:

    var
      MSG: string;
      Inserted, Modified: string;
      States: TUpdateStatusSet;
      MySet: Byte;
    
    begin
      while not ClientDataSet.Eof do
      begin
        //That's the part that interest us
        //Convert that integer you stored in the database or whatever 
        //place to a Byte and, in the sequence, to your set type.
        iSet := Byte(ClientDatasetMyIntegerField);// Sets are one byte, so they
                                                  //  fit on a byte variable  
        States := TUpdateStatusSet(iSet);
        //Conversion finished, below is just interface stuff
    
    
        if usInserted in States then
          Inserted := 'Yes';
        if usModified in States then
          Modified := 'Yes';
        MSG := Format('Register Num: %d. Inserted: %s. Modified:%s',
                      [ClientDataSet.RecNo, Inserted, Alterted]);
        ShowMessage( MSG );
        ClientDataset.Next;
      end;
    
    end;
    
    0 讨论(0)
  • 2021-02-06 12:52

    You could use a TBytesField or a TBlobField

    ClientDataSet1MySet: TBytesField, Size=32

    var
      MySet: set of Byte;
      Bytes: array of Byte;
    begin
      MySet := [1, 2, 4, 8, 16];
    
      // Write
      Assert(ClientDataSet1MySet.DataSize >= SizeOf(MySet), 'Data field is too small');
    
      SetLength(Bytes, ClientDataSet1MySet.DataSize);
      Move(MySet, Bytes[0], SizeOf(MySet));
      ClientDataSet1.Edit;
      ClientDataSet1MySet.SetData(@Bytes[0]);
      ClientDataSet1.Post;
    
      // Read
      SetLength(Bytes, ClientDataSet1MySet.DataSize);
      if ClientDataSet1MySet.GetData(@Bytes[0]) then
        Move(Bytes[0], MySet, SizeOf(MySet))
      else
        MySet := []; // NULL
    end;
    
    0 讨论(0)
  • 2021-02-06 13:01

    Based on the example of Andreas, but made somewhat simpler and clearer IMHO.

    Tested on XE2

    You could use a TBytesField or a TBlobField

    ClientDataSet1MySet: TBytesField, Size=32

    1) Writing

    var
      MySet: set of Byte;
      Bytes: TBytes;
    begin
      MySet := [0];
    
      // Write
      Assert(ClientDataSet1Test.DataSize >= SizeOf(MySet), 'Data field is too small');
    
      SetLength(Bytes, ClientDataSet1Test.DataSize);
      Move(MySet, Bytes[0], SizeOf(MySet));
      ClientDataSet1.Edit;
      ClientDataSet1Test.AsBytes := Bytes;
      ClientDataSet1.Post;
    end;
    

    2) Reading

    var
      MyResultSet: set of Byte;
    begin
      Move(ClientDataSet1Test.AsBytes[0], MyResultSet, ClientDataSet1Test.DataSize);
    end;
    
    0 讨论(0)
提交回复
热议问题