Tiêu đề khá nhiều nói lên tất cả. Tôi đang sử dụng một TClientDataset để lưu trữ một mảng các đối tượng, và một trong các đối tượng có một thành viên được định nghĩa là một bộ của một kiểu liệt kê. Như tôi đã hiểu, các bộ Delphi là các bitfield có kích thước có thể thay đổi từ 1 đến 32 byte tùy thuộc vào lượng dữ liệu chúng chứa, và Delphi không định nghĩa một TSetField. Tôi nên sử dụng loại trường nào để tải giá trị này vào?Cách tốt nhất để lưu trữ tập Delphi trong tập dữ liệu là gì?
Trả lời
Bạn có thể sử dụng một TBytesField hoặc một TBlobField
ClientDataSet1MySet: TBytesField, Kích thước = 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;
Nó tốt hơn tôi. Và rõ ràng hơn ... Cool –
1) Để làm cho mẫu của bạn rõ ràng hơn, tôi đề xuất thay đổi "ClientDataSet1MySet.SetData (@Bytes [0])" thành "ClientDataSet1MySet.AsBytes: = Bytes" 2) Trong // Read block (trên dòng Move), tôi nghĩ rằng bạn phải thay đổi "SizeOf (MySet)" thành "ClientDataSet1MySet.DataSize" để nhất quán. – rvheddeg
Bạn có thể chuyển đổi chúng sang Byte, như thế này:
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;
Để khắc phục ở bất kỳ đâu:
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;
Chỉ hoạt động tốt cho đến khi bạn cần hơn 32 bit. Các bộ đi lên tới 256 bit và tôi đang ở trong tình huống mà tôi có thể cần một phần nhỏ của không gian đó. –
Tôi sẽ cố gắng điều chỉnh điều này theo kịch bản đó. –
Dựa trên ví dụ về Andreas, nhưng làm IMHO đơn giản và rõ ràng hơn.
Thử nghiệm trên XE2
Bạn có thể sử dụng một TBytesField hoặc một TBlobField
ClientDataSet1MySet: TBytesField, Kích thước = 32
1) Viết
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) Đọc
var
MyResultSet: set of Byte;
begin
Move(ClientDataSet1Test.AsBytes[0], MyResultSet, ClientDataSet1Test.DataSize);
end;
Xem thêm [Cách lưu/tải Tập hợp loại?] (Http://stackoverflow.com/q/9553510/757830). – NGLN