├── .gitignore ├── LICENSE ├── README.md ├── examples ├── Example1.Form.dfm ├── Example1.Form.pas ├── Example1.dpr └── Example1.dproj └── source └── urs.DataSetHelper.pas /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | 48 | # Delphi autogenerated files (duplicated info) 49 | *.cfg 50 | *.hpp 51 | *Resource.rc 52 | 53 | # Delphi local files (user-specific info) 54 | *.local 55 | *.identcache 56 | *.projdata 57 | *.tvsconfig 58 | *.dsk 59 | 60 | # Delphi history and backups 61 | __history/ 62 | __recovery/ 63 | *.~* 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | 68 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss 69 | modules/ 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Uwe Raabe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Note: 2 | The only unit is now part or _CmonLib_: https://github.com/UweRaabe/CmonLib. The latest version can be find over there while this repository will stay as is. 3 | 4 | # DataSetEnumerator 5 | TDataSet helper classes to simplify access to TDataSet fields and make TDataSet work with a for-in-loop. 6 | 7 | The enumerator is implemented using a class helper, which makes it available for all TDataSet descendants. It uses a generic approach allowing type safety as well as code completion. 8 | 9 | Let’s have a look at the public section of TDataSetHelper: 10 | 11 | ```Delphi 12 | type 13 | TDataSetHelper = class helper for TDataSet 14 | public 15 | function GetCurrentRec: T; 16 | procedure SetCurrentRec(AInstance: T); 17 | procedure LoadInstanceFromCurrent(AInstance: T); 18 | procedure StoreInstanceToCurrent(AInstance: T); 19 | function Records(AInstance: T): IRecords; overload; 20 | function Records: IRecords; overload; 21 | end; 22 | ``` 23 | The first thing to mention is that the enumerator is not exposed by the dataset directly. Instead we have two overloaded functions named _Records_ returning the same generic interface _IRecords_. 24 | 25 | ```Delphi 26 | IRecords = interface 27 | function GetEnumerator: TDataSetEnumerator; 28 | end; 29 | ``` 30 | As you see, this interface has no other task than to expose the actual enumerator. The reason is to make use of reference counting to control the lifetime of the inner objects. I also found no other way to get a generic enumerator. 31 | 32 | Back to the class helper we notice that one of these functions has a generic constraint _record_, while the other one has a similar constraint for _class_, with the addition of taking a parameter with that class type. A similar approach is used for the method pairs _GetCurrentRec/SetCurrentRec_ and LoadInstanceFromCurrent_/StoreInstanceToCurrent_. Besides the enumerator support the class helper obviously allows loading and storing the current dataset record into/from a record or class instance of the given type. 33 | 34 | Before diving too much into the implementation details let’s have a look at how this can be used in our code. The example that comes with the sources contains a _ClientDataset_ made up from the _employee.xml_ file which can be found in Delphis samples/data folder. 35 | 36 | In the code we declare a record that matches the fields in that dataset. 37 | 38 | ```Delphi 39 | type 40 | TEmployee = record 41 | EmpNo: Integer; 42 | LastName: string; 43 | FirstName: string; 44 | PhoneExt: string; 45 | HireDate: TDateTime; 46 | Salary: Double; 47 | end; 48 | ``` 49 | This is the code using the enumerator to fill a memo with some information about our employees. 50 | 51 | ```Delphi 52 | var 53 | Employee: TEmployee; 54 | S: string; 55 | begin 56 | { List all emplyoees with First- and LastName in the Memo. Employees hired 57 | before 01/01/1991 are marked with an * in front of their names. } 58 | MemOutput.Lines.BeginUpdate; 59 | try 60 | MemOutput.Lines.Clear; 61 | for Employee in QuEmployee.Records do begin 62 | S := Trim(Format('%s %s', [Employee.FirstName, Employee.LastName])); 63 | if Employee.HireDate < EncodeDate(1991, 1, 1) then 64 | S := '*' + S; 65 | MemOutput.Lines.Add(S); 66 | end; 67 | finally 68 | MemOutput.Lines.EndUpdate; 69 | end; 70 | end; 71 | ``` 72 | Now a use case for _GetCurrentRec_: 73 | 74 | ```Delphi 75 | var 76 | Employee: TEmployee; 77 | begin 78 | { Show the employee's name and the hire date. } 79 | Employee := QuEmployee.GetCurrentRec; 80 | ShowMessage(Format('%s %s was hired on %s', 81 | [Employee.FirstName, Employee.LastName, FormatDateTime('dddddd', Employee.HireDate)])); 82 | end; 83 | ``` 84 | The _TCustomer_ class is bound to the _customer.xml_ table and is a bit more sophisticated: 85 | 86 | ```Delphi 87 | type 88 | TCustomer = class 89 | private 90 | [DBField('CustNo')] 91 | FCustNo: Double; 92 | FCompany: string; 93 | FAddress1: string; 94 | FAddress2: string; 95 | FCity: string; 96 | FState: string; 97 | [DBField('Zip')] 98 | FZipCode: string; 99 | FCountry: string; 100 | FPhone: string; 101 | FFAX: string; 102 | FTaxRate: Double; 103 | FContact: string; 104 | FLastInvoiceDate: TDateTime; 105 | function GetCustNo: Integer; 106 | procedure SetCustNo(const Value: Integer); 107 | public 108 | [DBField('Addr1')] 109 | property Address1: string read FAddress1 write FAddress1; 110 | [DBField('Addr2')] 111 | property Address2: string read FAddress2 write FAddress2; 112 | property City: string read FCity write FCity; 113 | property Company: string read FCompany write FCompany; 114 | property Contact: string read FContact write FContact; 115 | property Country: string read FCountry write FCountry; 116 | [DBField(false)] 117 | property CustNo: Integer read GetCustNo write SetCustNo; 118 | property FAX: string read FFAX write FFAX; 119 | property LastInvoiceDate: TDateTime read FLastInvoiceDate write FLastInvoiceDate; 120 | property Phone: string read FPhone write FPhone; 121 | property State: string read FState write FState; 122 | property TaxRate: Double read FTaxRate write FTaxRate; 123 | property ZipCode: string read FZipCode write FZipCode; 124 | end; 125 | ``` 126 | There are some attributes controlling the mapping of the properties and fields to the dataset fields. Properties _Address1_ and _Address2_ are mapped to the dataset fields _Addr1_ and _Addr2_. Property _CustNo_ is not mapped to any field as it is of type integer while the corresponding table field is of type float. Instead we map _FCustNo_ to that dataset field which happens to have the proper type for that. Last _FZipCode_ is mapped to dataset field _Zip_. The other properties are automatically mapped to their corresponding dataset fields. This is controlled by the mapping mode taken from the global variable _DefaultDBFieldsMapping_, which is initialized with _mapAuto_. 127 | 128 | ```Delphi 129 | type 130 | TDBFieldsMapping = (mapAuto, mapManual); 131 | 132 | var 133 | DefaultDBFieldsMapping: TDBFieldsMapping = mapAuto; 134 | ``` 135 | 136 | The _DBFields_ attribute allows to override this for each class. 137 | 138 | ```Delphi 139 | type 140 | [DBFields(mapManual)] 141 | TSomeManuallyMappedClass = class 142 | private 143 | [DBField('SomeDBFieldName')] 144 | FSomeField: Integer; 145 | [DBField('SomeOtherDBFieldName')] 146 | FSomeOtherField: string; 147 | FSomeNotMappedField: Double; 148 | public 149 | property SomeField: Integer read FSomeField write FSomeField; 150 | property SomeOtherField: string read FSomeOtherField write FSomeOtherField; 151 | end; 152 | ``` 153 | 154 | The enumerator example for _TCustomer_ needs an instance of that class to work with. Due to type inference we can omit the generic type here. 155 | 156 | ```Delphi 157 | var 158 | Customer: TCustomer; 159 | S: string; 160 | begin 161 | { List all Customers with their Name and City in the Memo. Customers outside 162 | the US have their Country enclosed in brackets appended. } 163 | MemOutput.Lines.BeginUpdate; 164 | try 165 | MemOutput.Lines.Clear; 166 | Customer := TCustomer.Create; 167 | try 168 | for Customer in QuCustomer.Records(Customer) do begin 169 | S := Format('%d: %s - %s %s', [Customer.CustNo, Customer.Company, Customer.Zip, Customer.City]); 170 | if Customer.Country <> 'US' then 171 | S := S + ' (' + Customer.Country + ')'; 172 | MemOutput.Lines.Add(S); 173 | end; 174 | finally 175 | Customer.Free; 176 | end; 177 | finally 178 | MemOutput.Lines.EndUpdate; 179 | end; 180 | end; 181 | ``` 182 | Loading and saving data is done in a similar way. 183 | 184 | ```Delphi 185 | var 186 | Customer: TCustomer; 187 | begin 188 | { Set LastInvoiceDate to current date/time } 189 | Customer := TCustomer.Create; 190 | try 191 | QuCustomer.LoadInstanceFromCurrent(Customer); 192 | Customer.LastInvoiceDate := Now; 193 | QuCustomer.Edit; 194 | QuCustomer.StoreInstanceToCurrent(Customer); 195 | QuCustomer.Post; 196 | finally 197 | Customer.Free; 198 | end; 199 | end; 200 | ``` 201 | -------------------------------------------------------------------------------- /examples/Example1.Form.dfm: -------------------------------------------------------------------------------- 1 | object Form1: TForm1 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form1' 5 | ClientHeight = 569 6 | ClientWidth = 1062 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | OnCreate = FormCreate 15 | PixelsPerInch = 96 16 | TextHeight = 13 17 | object PnlTop: TPanel 18 | Left = 0 19 | Top = 0 20 | Width = 1062 21 | Height = 52 22 | Align = alTop 23 | TabOrder = 0 24 | object BtnListEmployees: TButton 25 | Left = 11 26 | Top = 6 27 | Width = 103 28 | Height = 35 29 | Caption = 'List Employees' 30 | TabOrder = 0 31 | OnClick = BtnListEmployeesClick 32 | end 33 | object BtnListCustomers: TButton 34 | Left = 147 35 | Top = 6 36 | Width = 103 37 | Height = 35 38 | Caption = 'List Customers' 39 | TabOrder = 1 40 | OnClick = BtnListCustomersClick 41 | end 42 | end 43 | object PnlMain: TPanel 44 | Left = 0 45 | Top = 52 46 | Width = 1062 47 | Height = 517 48 | Align = alClient 49 | Caption = 'PnlMain' 50 | TabOrder = 1 51 | object MemOutput: TMemo 52 | Left = 1 53 | Top = 1 54 | Width = 274 55 | Height = 307 56 | Align = alLeft 57 | Lines.Strings = ( 58 | 'Memo1') 59 | TabOrder = 0 60 | end 61 | object GrdEmployee: TDBGrid 62 | Left = 275 63 | Top = 1 64 | Width = 786 65 | Height = 307 66 | Align = alClient 67 | DataSource = DsEmployee 68 | TabOrder = 1 69 | TitleFont.Charset = DEFAULT_CHARSET 70 | TitleFont.Color = clWindowText 71 | TitleFont.Height = -11 72 | TitleFont.Name = 'Tahoma' 73 | TitleFont.Style = [] 74 | OnDblClick = GrdEmployeeDblClick 75 | end 76 | object GrdCustomer: TDBGrid 77 | Left = 1 78 | Top = 308 79 | Width = 1060 80 | Height = 208 81 | Align = alBottom 82 | DataSource = DsCustomer 83 | TabOrder = 2 84 | TitleFont.Charset = DEFAULT_CHARSET 85 | TitleFont.Color = clWindowText 86 | TitleFont.Height = -11 87 | TitleFont.Name = 'Tahoma' 88 | TitleFont.Style = [] 89 | OnDblClick = GrdCustomerDblClick 90 | end 91 | end 92 | object DsEmployee: TDataSource 93 | DataSet = QuEmployee 94 | Left = 70 95 | Top = 67 96 | end 97 | object DsCustomer: TDataSource 98 | DataSet = QuCustomer 99 | Left = 110 100 | Top = 66 101 | end 102 | object QuEmployee: TClientDataSet 103 | PersistDataPacket.Data = { 104 | 890700009619E0BD010000001800000006002A00000003000000DB0005456D70 105 | 4E6F0400010000000000084C6173744E616D6501004900000001000557494454 106 | 480200020014000946697273744E616D65010049000000010005574944544802 107 | 0002000F000850686F6E65457874010049000000010005574944544802000200 108 | 040008486972654461746508000800000000000653616C617279080004000000 109 | 000003000D44454641554C545F4F52444552020082000100000001000B505249 110 | 4D4152595F4B455902008200010000000100044C434944040001000904000000 111 | 000002000000064E656C736F6E07526F626572746F033235300000EA4F4F87CC 112 | 42000000000088E3400000000400000005596F756E6705427275636503323333 113 | 0000EA4F4F87CC42000000008019EB4000000005000000074C616D6265727403 114 | 4B696D02323200001A4FB687CC4200000000006AD84000000008000000074A6F 115 | 686E736F6E064C65736C696503343130000086A74B88CC42000000008076D840 116 | 0000000900000006466F72657374045068696C033232390000AE8D6A88CC4200 117 | 0000008076D8400000000B00000006576573746F6E054B2E204A2E0233340000 118 | 18A82E8BCC42000000009E41E0400000000C000000034C656505546572726903 119 | 3235360000C8723A8CCC42000000008022E6400000000E0000000448616C6C07 120 | 53746577617274033232370000E4FE918CCC420000000054D6E0400000000F00 121 | 000005596F756E67094B6174686572696E65033233310000B0BEAB8CCC420000 122 | 000000D4D740000000140000000C50617061646F706F756C6F73054368726973 123 | 0338383700003875058BCC42000000008076D840000000180000000646697368 124 | 65720450657465033838380000DC7C938DCC42000000000080D6400000001C00 125 | 00000642656E6E657403416E6E013500006020018FCC429A99999959D6E04000 126 | 00001D00000008446520536F757A6105526F6765720332383800006EE62C8FCC 127 | 420000000000E7D840000000220000000742616C6477696E054A616E65740132 128 | 000000B97C8FCC420000000000C1D64000000024000000065265657665730552 129 | 6F676572013600004AD8D68FCC4200000000806AE04000000025000000095374 130 | 616E73627572790657696C6C6965013700004AD8D68FCC42000000000027E340 131 | 0000002C0000000550686F6E67064C65736C69650332313600004C443B90CC42 132 | 00000000C0B3E3400000002D0000000A52616D616E617468616E054173686F6B 133 | 033230390000E62FD390CC4248E17A149E41E0400000002E0000000853746561 134 | 646D616E0657616C74657203323130000056C9E790CC4200000000C023D34000 135 | 000034000000094E6F72647374726F6D054361726F6C0334323000000AD57291 136 | CC42000000000094B1400000003D000000054C65756E67044C756B6501330000 137 | 04BFD892CC420000000080D8E04000000041000000074F27427269656E085375 138 | 6520416E6E65033837370000204B3093CC4200000000C08ADE40000000470000 139 | 000742757262616E6B0B4A656E6E69666572204D2E03323839000042846B93CC 140 | 42000000008022E640004000480000000A5375746865726C616E6407436C6175 141 | 646961000028647893CC4200000000606EE1400000005300000006426973686F 142 | 700444616E61033239300000B489E493CC420000000000F9E540000000550000 143 | 00094D6163446F6E616C64074D61727920532E033437370000B489E493CC4200 144 | 000000606EE1400000005E0000000857696C6C69616D730552616E6479033839 145 | 320000ECA19394CC42000000000039DC40000000690000000642656E64657209 146 | 4F6C6976657220482E033235350000E2B33095CC4200000000E0F7E140000000 147 | 6B00000004436F6F6B054B6576696E033839340000BA645B96CC420000000080 148 | 55E1400000006D0000000542726F776E054B656C6C79033230320000441E6396 149 | CC4200000000005EDA400000006E000000064963686964610459756B69023232 150 | 0000441E6396CC42000000004016D940000000710000000450616765044D6172 151 | 790338343500004EA30F97CC42000000000070E7400000007200000006506172 152 | 6B65720442696C6C0332343700004A629097CC42000000000017E14000000076 153 | 0000000859616D616D6F746F0754616B617368690232330000AEA1DD97CC4200 154 | 00000000BDDF4000000079000000074665727261726907526F626572746F0131 155 | 0000A8F4F997CC420000000080C6E3400000007F0000000859616E6F77736B69 156 | 074D69636861656C033439320000B00D4298CC4200000000007CE54000400086 157 | 00000004476C6F6E074A6163717565730000341A6698CC4200000000C045D840 158 | 00000088000000074A6F686E736F6E0553636F7474033236350000FA2C9C98CC 159 | 42C3F5285C3FDFDD400000008A00000005477265656E04542E4A2E0332313800 160 | 00C8581A99CC42000000000094E1400040008D000000074F73626F726E650650 161 | 696572726500001A91BC99CC42000000000062E140000000900000000A4D6F6E 162 | 74676F6D657279044A6F686E0338323000008E029A9ACC4200000000606EE140 163 | 000000910000000C4775636B656E6865696D6572044D61726B0332323100007C 164 | FBEE9ACC42000000000040DF40} 165 | Active = True 166 | Aggregates = <> 167 | Params = <> 168 | Left = 64 169 | Top = 152 170 | end 171 | object QuCustomer: TClientDataSet 172 | PersistDataPacket.Data = { 173 | 451D00009619E0BD01000000180000000D003700000003000000910106437573 174 | 744E6F080004000000000007436F6D70616E7901004900000001000557494454 175 | 48020002001E000541646472310100490000000100055749445448020002001E 176 | 000541646472320100490000000100055749445448020002001E000443697479 177 | 0100490000000100055749445448020002000F00055374617465010049000000 178 | 0100055749445448020002001400035A69700100490000000100055749445448 179 | 020002000A0007436F756E747279010049000000010005574944544802000200 180 | 14000550686F6E650100490000000100055749445448020002000F0003464158 181 | 0100490000000100055749445448020002000F00075461785261746508000400 182 | 0000000007436F6E746163740100490000000100055749445448020002001400 183 | 0F4C617374496E766F69636544617465080008000000000003000D4445464155 184 | 4C545F4F52444552020082000100000001000B5052494D4152595F4B45590200 185 | 8200010000000100044C43494404000100090400000000000000000000000014 186 | 9340114B6175616920446976652053686F70706513342D393736205375676172 187 | 6C6F616620487779095375697465203130330B4B61706161204B617561690248 188 | 490A39343736362D313233340255530C3830382D3535352D303236390C383038 189 | 2D3535352D3032373800000000000021400C4572696361204E6F726D616E000C 190 | DBC6B59DCC42004014000000000000003C934006556E6973636F0C504F20426F 191 | 78205A2D3534370846726565706F727407426168616D61730C3830392D353535 192 | 2D333931350C3830392D3535352D3439353800000000000000000F47656F7267 193 | 6520576561746865727300D497E9F09CCC42004014000000000000001C95400B 194 | 53696768742044697665720E31204E657074756E65204C616E650B4B61746F20 195 | 506170686F73064379707275730C3335372D362D3837363730380C3335372D36 196 | 2D38373039343300000000000000000F5068796C6C69732053706F6F6E657200 197 | 181638A49CCC42004014000000000000002895401D4361796D616E2044697665 198 | 727320576F726C6420556E6C696D697465640A504F20426F78203534310C4772 199 | 616E64204361796D616E1342726974697368205765737420496E646965730C30 200 | 31312D352D3639373034340C3031312D352D3639373036340000000000000000 201 | 0A4A6F65204261696C657900E0F509A892CC4200400000000000000000309540 202 | 18546F6D2053617779657220446976696E672043656E747265153633322D3120 203 | 54686972642046727964656E686F6A0D43687269737469616E73746564095374 204 | 2E2043726F69780530303832301155532056697267696E2049736C616E64730C 205 | 3530342D3739382D333032320C3530342D3739382D3737373200000000000000 206 | 000C43687269732054686F6D617300F01A992993CC4200000000000000000000 207 | 90954015426C7565204A61636B20417175612043656E7465721632332D373338 208 | 2050616464696E67746F6E204C616E6509537569746520333130075761697061 209 | 68750248490539393737360255530C3430312D3630392D373632330C3430312D 210 | 3630392D3934303300000000000000000E45726E657374204261727261747400 211 | 8078B9DA9CCC4200400000000000000000A095400F5649502044697665727320 212 | 436C75620B3332204D61696E2053742E0D43687269737469616E737465640953 213 | 742E2043726F69780530323830301155532056697267696E2049736C616E6473 214 | 0C3830392D3435332D353937360C3830392D3435332D35393332000000000000 215 | 00001352757373656C6C204368726973746F7068657200DC0E19B59DCC420040 216 | 00000000000000009897400E4F6365616E2050617261646973650B504F20426F 217 | 7820383734350B4B61696C75612D4B6F6E610248490539343735360255530C38 218 | 30382D3535352D383233310C3830382D3535352D383435300000000000000000 219 | 0C5061756C20476172646E6572005882F0DA9CCC4200401400000000000000A4 220 | 97401446616E7461737469717565204171756174696361145A33322039393920 221 | 233132412D373720412E412E06426F676F746108436F6C756D6269610C303537 222 | 2D312D3737333433340C3035372D312D37373334323100000000000000000A53 223 | 7573616E20576F6E670064071BB79BCC42004000000000000000003C9840124D 224 | 61726D6F742044697665727320436C75620D38373220517565656E2053742E09 225 | 4B69746368656E6572074F6E746172696F0747334E203245310643616E616461 226 | 0C3431362D3639382D303339390C3432362D3639382D30333939000000000000 227 | 00000B4A6F796365204D617273680008486FE78CCC4200400000000000000000 228 | 609840105468652044657074682043686172676515313532343320556E646572 229 | 7761746572204677792E084D61726174686F6E02464C0533353030330255530C 230 | 3830302D3535352D333739380C3830302D3535352D3033353300000000000000 231 | 000F53616D2057697468657273706F6F6E0030E2A4B49ACC4200400000000000 232 | 0000006C98400B426C75652053706F727473153230332031327468204176652E 233 | 20426F7820373436094769726962616C6469024F520539313138370255530C36 234 | 31302D3737322D363730340C3631302D3737322D363839380000000000000000 235 | 0D54686572657361204B756E656300F80031FC8FCC4200400000000000000000 236 | 609940104D616B616920534355424120436C75620B504F20426F782038353334 237 | 0B4B61696C75612D4B6F6E610248490539343735360255530C3331372D363439 238 | 2D393039380C3331372D3634392D3637383700000000000000000B446F6E6E61 239 | 2053696175730028DE34749DCC4200400000000000000000B499400B41637469 240 | 6F6E20436C75620D504F20426F7820353435312D460853617261736F74610246 241 | 4C0533323237340255530C3831332D3837302D303233390C3831332D3837302D 242 | 303238320000000000000000104D69636861656C20537075726C696E67009812 243 | D5F798CC4200401000000000000000CC9940144A616D61696361205343554241 244 | 2043656E74726509504F20426F78203638064E656772696C074A616D61696361 245 | 0B5765737420496E646965730C3031312D332D3639373034330C3031312D332D 246 | 36393730343300000000000000000E426172626172612048617276657900380E 247 | 71BF94CC4200400000000000000000409A400E49736C616E642046696E646572 248 | 73153631333320312F332053746F6E65204176656E75650E53742053696D6F6E 249 | 732049736C650247410533323532310255530C3731332D3432332D353637350C 250 | 3731332D3432332D3536373600000000000000000E4465736D6F6E64204F7274 251 | 65676100901CDD669DCC4200401400000000000000009F4012416476656E7475 252 | 726520556E6465727365610A504F20426F78203734340B42656C697A65204369 253 | 74790642656C697A650C3031312D33342D30393035340C3031312D33342D3039 254 | 30363400000000000000000F476C6F72696120476F6E7A616C657300980FD9D4 255 | 9CCC42004000000000000000008CA04010426C75652053706F72747320436C75 256 | 62163633333635204E657A20506572636520537472656574054C6172676F0246 257 | 4C0533343638340255530C3631322D3839372D303334320C3631322D3839372D 258 | 3033343800000000000000000E48617272792042617468626F6E65006864839D 259 | 8CCC4200400000000000000000AEA040154672616E6B27732044697665727320 260 | 537570706C791331343535204E6F72746820343474682053742E06457567656E 261 | 65024F520539303432370255530C3530332D3535352D323737380C3530332D35 262 | 35352D3237363900000000000000000D4C6C6F79642046656C6C6F777300C82E 263 | C61A89CC4200400000000000000000D8A0401244617679204A6F6E657327204C 264 | 6F636B65721432343620536F757468203136746820506C6163650956616E636F 265 | 75766572024243074B3856203950310643616E6164610C3830332D3530392D30 266 | 3131320C3830332D3530392D3035353300000000000000000C54616E79612057 267 | 61676E65720058886ACA91CC4200401400000000000000E6A0400C5343554241 268 | 2048656176656E0D504F20426F7820512D38383734064E617373617507426168 269 | 616D61730C3031312D33322D30393438350C3031312D33322D30393438350000 270 | 00000000000010526F62657274204D696368656C696E6400B0DAC69E8ECC4200 271 | 401400000000000000EAA040185368616E6772692D4C612053706F7274732043 272 | 656E7465720D504F20426F7820442D353439350846726565706F727407426168 273 | 616D61730C3031312D33322D30383537340C3031312D33322D34343933380000 274 | 0000000000000E4672616E6B2050616E69616775610074867D3289CC42004010 275 | 0000000000000016A24015446976657273206F6620436F7266752C20496E632E 276 | 114D61726D6F73657420506C6163652035340F4179696F73204D617474686169 277 | 6F7305436F726675064772656563650C33302D3636312D38383336340C33302D 278 | 3636312D303539343300000000000000000D436861726C6573204C6F70657A00 279 | 4028065C9BCC420040000000000000000064A240104B69726B20456E74657270 280 | 72697365730C34322041717561204C616E6507486F7573746F6E025458053737 281 | 3037390255530C3731332D3535362D363433370C3731332D3535362D31303733 282 | 00000000000000000D5275646F6C706820436C61757300545FD51A9ACC420040 283 | 00000000000000003EA7401147656F726765204265616E202620436F2E132337 284 | 33204B696E672053616C6D6F6E20576179064C75676F6666024E430532393037 285 | 380255530C3830332D3433382D323737310C3830332D3433382D333030330000 286 | 0000000000000A42696C6C20577965727300386112AC9ACC4200400000000000 287 | 00000050A7401950726F66657373696F6E616C204469766572732C204C74642E 288 | 1034373334204D656C696E64612053742E06486F6F76657202414C0533323134 289 | 350255530C3230352D3535352D383333330C3230352D3535352D343035340000 290 | 0000000000000F536869726C6579204D617468657273001C4490F89ACC420040 291 | 0000000000000000C2A74014446976657273206F6620426C75652D677265656E 292 | 1036333420436F6D706C6578204176652E0650656C68616D02414C0533323134 293 | 350255530C3230352D3535352D373138340C3230352D3535352D363035390000 294 | 0000000000000A4E616E6379204265616E00988CDA4E9ACC4200400000000000 295 | 000000C4A74011476F6C6420436F61737420537570706C79133232332D422048 296 | 6F7573746F6E20506C616365064D6F62696C6502414C0533303639360255530C 297 | 3230352D3535352D323634300C3230352D3535352D3430393400000000000000 298 | 000C456C61696E652046616C6C7300A0F704A69BCC4200400000000000000000 299 | D6A7401553616E205061626C6F20446976652043656E74657211313730312D44 300 | 204E2042726F61647761790B53616E7461204D61726961024341053935343433 301 | 0255530C3832332D3034342D323931300C3832332D3034342D32393930000000 302 | 0000000000105061747269636961204F27427269656E0044EFE7BD9BCC420040 303 | 0000000000000000D8A74015556E64657277617465722053706F72747320436F 304 | 2E123335312D412053617261736F74612053742E0853616E204A6F7365024341 305 | 0539323139350255530C3430382D3836372D303539340C3430382D3836372D30 306 | 30393400000000000000000C446176652057616C6C696E6700F0E9F7659CCC42 307 | 00400000000000000000DAA74015416D65726963616E20534355424120537570 308 | 706C7914313733392041746C616E746963204176656E7565064C6F6D69746102 309 | 43410539313737300255530C3231332D3635342D303039320C3231332D363534 310 | 2D303039350000000000000000104C796E6E2043696E6369726970696E69002C 311 | AD736C9DCC4200400000000000000000DCA74013436174616D6172616E204469 312 | 766520436C756216426F782032363420506C65617375726520506F696E740F43 313 | 6174616C696E612049736C616E640243410539303734300255530C3231332D32 314 | 32332D303934310C3231332D3232332D3233323400000000000000000D4E6963 315 | 6F6C65204475706F6E7400B06C4BA79CCC4200400000000000000000DEA7400E 316 | 446976657227732047726F74746F14323436303120556E6976657273616C204C 317 | 616E6506446F776E65790243410539343232300255530C3231332D3433322D30 318 | 3039330C3231332D3433322D3438323100000000000000000A5065746572204F 319 | 77656E00148C75089DCC42004014000000000000009EA8400F4669736865726D 320 | 616E2773204579650B504F20426F7820373534320C4772616E64204361796D61 321 | 6E1342726974697368205765737420496E646965730C3830392D3535352D3436 322 | 38300C3830392D3535352D3436383900000000000000000C42657468616E204C 323 | 657769730030BCCCD99BCC4200400400000000000000ACA84013416374696F6E 324 | 20446976657220537570706C7910426C7565205370617220426F782023330A53 325 | 742E2054686F6D61730530303832301155532056697267696E2049736C616E64 326 | 730C32322D34342D3530303231310C32322D34342D3530303539360000000000 327 | 0000000E4D617269616E6E65204D696C6573004C85DB7598CC42004014000000 328 | 000000003EAC40134D6172696E612053435542412043656E74657216504F2042 329 | 6F78203832343338205A756C75203738333107436172616361730956656E657A 330 | 75656C610B35382D33332D36363232320B35382D33332D363630343900000000 331 | 000000000E5374657068656E20427279616E7400180C805C97CC420040000000 332 | 000000000020AF4014426C756520476C6173732048617070696E657373123633 333 | 343520572E2053686F7265204C616E650C53616E7461204D6F6E696361024341 334 | 0539303431300255530C3231332D3535352D313938340C3231332D3535352D31 335 | 393935000000000000000010436872697374696E65205461796C6F7200ACFD03 336 | 169DCC4200400000000000000000D8B04010446976657273206F662056656E69 337 | 63650E32323020456C6D205374726565740656656E69636502464C0533393232 338 | 340255530C3831332D3434332D323335360C3831332D3434332D393834320000 339 | 0000000000000C53696D6F6E6520477265656E00B823820A99CC420040000000 340 | 0000000000B3B1400F4F6E2D54617267657420534355424115372D3733373633 341 | 204E616E616B61776120526F61640857696E6E69706567084D616E69746F6261 342 | 074A3252203554330643616E6164610C3431362D3434352D303938380C343136 343 | 2D3434352D3032323300000000000000000D4272616D205068696C6C69707300 344 | C00E81CC99CC42004010000000000000002CB240114A616D616963612053756E 345 | 2C20496E632E0A504F20426F78203634330B52756E6177617920426179074A61 346 | 6D616963610B5765737420496E646965730C3830392D3535352D323734360C38 347 | 30392D3535352D3039323900000000000000000D4A6F6E617468616E20576573 348 | 740054C4A73A9DCC42004010000000000000004CB24012556E64657277617465 349 | 722046616E746173790A504F20426F7820383432094F63686F2052696F73074A 350 | 616D616963610B5765737420496E646965730C3830392D3535352D323231340C 351 | 3830392D3535352D3232333400000000000000000F4772616E742041696E7377 352 | 6F72746800E8BD1E199CCC42004014000000000000000CB440155072696E6365 353 | 73732049736C616E6420534355424111504F20426F7820333220576169796576 354 | 6F0754617665756E690446696A690A3637392D3331313932330A3637392D3331 355 | 3132303300000000000000000D416E6E65204D617269616368690034564F018B 356 | CC42004004000000000000001FB4401B43656E7472616C20556E646572776174 357 | 657220537570706C6965730A504F20426F78203733370C4A6F68616E6E657362 358 | 75726704323034321352657075626C696320536F2E204166726963610D32372D 359 | 31312D343433323435380D32372D31312D343433333235390000000000000000 360 | 0E4D61726961204576656E746F736800AC7945E59CCC42004014000000000000 361 | 002BB4401453616661726920556E64657220746865205365610B504F20426F78 362 | 20373435360C4772616E64204361796D616E1342726974697368205765737420 363 | 496E646965730C3830392D3430392D343233330C3830392D3430392D33303032 364 | 000000000000000009416E6E61205261636B00A8F851A398CC42004000000000 365 | 000000002DB440154C61727279277320446976696E67205363686F6F6C143335 366 | 3632204E5720427275636520537472656574094D696C7761756B6965024F5205 367 | 39363237370255530C3530332D3430332D373737370C3530332D3430332D3030 368 | 353900000000000000000E49736162656C6C65204E656563650074F660229BCC 369 | 420040140000000000000008B5400E546F726120546F726120546F72610D504F 370 | 20426F7820482D34353733064E617373617507426168616D61730C3830392D38 371 | 39382D303034330C3830392D3839382D3938363400000000000000000B4B6576 372 | 696E20526964657200989BFEBD9DCC420040000000000000000024B5400F5661 373 | 73686F6E2056656E747572657311373433204B6579686F6C6520436F75727408 374 | 486F6E6F6C756C750248490539323835360255530C3533322D3039392D303432 375 | 330C3533322D3039392D3636353400000000000000000B537573616E20536D69 376 | 746800583E61E399CC420040140000000000000038B5400F4469766572732D66 377 | 6F722D486972650D472E4F2E205020426F7820393104537576610446696A690A 378 | 3637392D3830343537360A3637392D30353933343500000000000000000A4A6F 379 | 652048617474657200203117FF99CC42004000000000000000008BB540104F63 380 | 65616E20416476656E747572657310504F20426F7820343636204B6968656904 381 | 4D6175690248490539353733360255530C3737362D3836382D393333340C3737 382 | 362D3836382D3935353300000000000000000A5061756C205374696C6C00B05D 383 | 11779DCC420040040000000000000047B84018556E6465727761746572205343 384 | 55424120436F6D70616E790C504F20426F7820536E20393108536F6D65727365 385 | 74045358424E074265726D7564610C3830392D3535352D313232350C3830392D 386 | 3535352D323434350000000000000000104D69636861656C2047726F73736D61 387 | 6E0068BC22B19ACC4200400000000000000000A8B8400D417175617469632044 388 | 72616D61123932312045766572676C61646573205761790554616D706102464C 389 | 0533303634330255530C3631332D3434322D373635340C3631332D3434322D37 390 | 36373800000000000000000C47696C6C69616E204F77656E007008D62F88CC42 391 | 0040040000000000000074B9401254686520446976696E6720436F6D70616E79 392 | 0B504F20426F7820383533350A53742E2054686F6D6173053030383230115553 393 | 2056697267696E2049736C616E64730B32322D34342D35303039380B32322D34 394 | 342D303938373800000000000000000B427269616E204D696C657300288AD3DC 395 | 99CC4200400400000000000000B6B940184E6F72776573742765722053435542 396 | 41204C696D697465640B504F20426F782036383334055061676574045053425A 397 | 074265726D7564610C3737382D3132332D303734350C3737382D3132332D3937 398 | 303500000000000000000C416E67656C61204A6F6E657300E8CBF6B89DCC4200 399 | 4000000000000000009CBA4017576174657273706F7574205343554241204365 400 | 6E7465721237383635204E45204261726265722043742E08506F72746C616E64 401 | 024F520539393237310255530C3530332D3635342D323433340C3530332D3635 402 | 342D3939383600000000000000000E5269636861726420486F7573657200048A 403 | 36919CCC420040100000000000008038C340184E657074756E65277320547269 404 | 64656E7420537570706C790A504F20426F7820313239064E656772696C074A61 405 | 6D616963610B5765737420496E646965730C3737382D3839372D333534360C37 406 | 37382D3839372D3636343300000000000000000D4C6F75697365204672616E6B 407 | 7300446FBD72A0CC42} 408 | Active = True 409 | Aggregates = <> 410 | Params = <> 411 | Left = 168 412 | Top = 152 413 | end 414 | end 415 | -------------------------------------------------------------------------------- /examples/Example1.Form.pas: -------------------------------------------------------------------------------- 1 | unit Example1.Form; 2 | 3 | interface 4 | 5 | { Example showing the use of the uDataSetHelper unit } 6 | 7 | uses 8 | System.Classes, 9 | Data.DB, Datasnap.DBClient, 10 | Vcl.Controls, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Forms, Vcl.Grids, Vcl.DBGrids; 11 | 12 | type 13 | TForm1 = class(TForm) 14 | MemOutput: TMemo; 15 | PnlTop: TPanel; 16 | PnlMain: TPanel; 17 | BtnListEmployees: TButton; 18 | BtnListCustomers: TButton; 19 | GrdEmployee: TDBGrid; 20 | DsEmployee: TDataSource; 21 | GrdCustomer: TDBGrid; 22 | DsCustomer: TDataSource; 23 | QuEmployee: TClientDataSet; 24 | QuCustomer: TClientDataSet; 25 | procedure FormCreate(Sender: TObject); 26 | procedure BtnListEmployeesClick(Sender: TObject); 27 | procedure BtnListCustomersClick(Sender: TObject); 28 | procedure GrdCustomerDblClick(Sender: TObject); 29 | procedure GrdEmployeeDblClick(Sender: TObject); 30 | private 31 | public 32 | end; 33 | 34 | var 35 | Form1: TForm1; 36 | 37 | implementation 38 | 39 | uses 40 | System.Sysutils, 41 | Vcl.Dialogs, 42 | MidasLib, 43 | urs.DataSetHelper; 44 | 45 | {$R *.dfm} 46 | 47 | type 48 | TEmployee = record 49 | EmpNo: Integer; 50 | LastName: string; 51 | FirstName: string; 52 | PhoneExt: string; 53 | HireDate: TDateTime; 54 | Salary: Double; 55 | end; 56 | 57 | TCustomer = class 58 | private 59 | [DBField('CustNo')] 60 | FCustNo: Double; 61 | FCompany: string; 62 | FAddress1: string; 63 | FAddress2: string; 64 | FCity: string; 65 | FState: string; 66 | [DBField('Zip')] 67 | FZipCode: string; 68 | FCountry: string; 69 | FPhone: string; 70 | FFAX: string; 71 | FTaxRate: Double; 72 | FContact: string; 73 | FLastInvoiceDate: TDateTime; 74 | function GetCustNo: Integer; 75 | procedure SetCustNo(const Value: Integer); 76 | public 77 | [DBField('Addr1')] 78 | property Address1: string read FAddress1 write FAddress1; 79 | [DBField('Addr2')] 80 | property Address2: string read FAddress2 write FAddress2; 81 | property City: string read FCity write FCity; 82 | property Company: string read FCompany write FCompany; 83 | property Contact: string read FContact write FContact; 84 | property Country: string read FCountry write FCountry; 85 | [DBField(false)] 86 | property CustNo: Integer read GetCustNo write SetCustNo; 87 | property FAX: string read FFAX write FFAX; 88 | property LastInvoiceDate: TDateTime read FLastInvoiceDate write FLastInvoiceDate; 89 | property Phone: string read FPhone write FPhone; 90 | property State: string read FState write FState; 91 | property TaxRate: Double read FTaxRate write FTaxRate; 92 | property ZipCode: string read FZipCode write FZipCode; 93 | end; 94 | 95 | type 96 | [DBFields(mapManual)] 97 | TSomeManuallyMappedClass = class 98 | private 99 | [DBField('SomeDBFieldName')] 100 | FSomeField: Integer; 101 | [DBField('SomeOtherDBFieldName')] 102 | FSomeOtherField: string; 103 | FSomeNotMappedField: Double; 104 | public 105 | property SomeField: Integer read FSomeField write FSomeField; 106 | property SomeOtherField: string read FSomeOtherField write FSomeOtherField; 107 | end; 108 | 109 | 110 | function TCustomer.GetCustNo: Integer; 111 | begin 112 | result := Round(FCustNo); 113 | end; 114 | 115 | procedure TCustomer.SetCustNo(const Value: Integer); 116 | begin 117 | FCustNo := Value; 118 | end; 119 | 120 | procedure TForm1.FormCreate(Sender: TObject); 121 | begin 122 | QuEmployee.Active := true; 123 | QuCustomer.Active := true; 124 | end; 125 | 126 | procedure TForm1.BtnListEmployeesClick(Sender: TObject); 127 | var 128 | Employee: TEmployee; 129 | S: string; 130 | begin 131 | { List all emplyoees with First- and LastName in the Memo. Employees hired 132 | before 01/01/1991 are marked with an * in front of their names. } 133 | MemOutput.Lines.BeginUpdate; 134 | try 135 | MemOutput.Lines.Clear; 136 | for Employee in QuEmployee.Records do begin 137 | S := Trim(Format('%s %s', [Employee.FirstName, Employee.LastName])); 138 | if Employee.HireDate < EncodeDate(1991, 1, 1) then 139 | S := '*' + S; 140 | MemOutput.Lines.Add(S); 141 | end; 142 | finally 143 | MemOutput.Lines.EndUpdate; 144 | end; 145 | end; 146 | 147 | procedure TForm1.BtnListCustomersClick(Sender: TObject); 148 | var 149 | Customer: TCustomer; 150 | S: string; 151 | begin 152 | { List all Customers with their Name and City in the Memo. Customers outside 153 | the US have their Country enclosed in brackets appended. } 154 | MemOutput.Lines.BeginUpdate; 155 | try 156 | MemOutput.Lines.Clear; 157 | Customer := TCustomer.Create; 158 | try 159 | for Customer in QuCustomer.Records(Customer) do begin 160 | S := Format('%d: %s - %s %s', [Customer.CustNo, Customer.Company, Customer.ZipCode, Customer.City]); 161 | if Customer.Country <> 'US' then 162 | S := S + ' (' + Customer.Country + ')'; 163 | MemOutput.Lines.Add(S); 164 | end; 165 | finally 166 | Customer.Free; 167 | end; 168 | finally 169 | MemOutput.Lines.EndUpdate; 170 | end; 171 | end; 172 | 173 | procedure TForm1.GrdCustomerDblClick(Sender: TObject); 174 | var 175 | Customer: TCustomer; 176 | begin 177 | { Set LastInvoiceDate to current date/time } 178 | Customer := TCustomer.Create; 179 | try 180 | QuCustomer.LoadInstanceFromCurrent(Customer); 181 | Customer.LastInvoiceDate := Now; 182 | QuCustomer.Edit; 183 | QuCustomer.StoreInstanceToCurrent(Customer); 184 | QuCustomer.Post; 185 | finally 186 | Customer.Free; 187 | end; 188 | end; 189 | 190 | procedure TForm1.GrdEmployeeDblClick(Sender: TObject); 191 | var 192 | Employee: TEmployee; 193 | begin 194 | { Show the employee's name and the hire date. } 195 | Employee := QuEmployee.GetCurrentRec; 196 | ShowMessage(Format('%s %s was hired on %s', [Employee.FirstName, Employee.LastName, FormatDateTime('dddddd', Employee.HireDate)])); 197 | end; 198 | 199 | end. 200 | -------------------------------------------------------------------------------- /examples/Example1.dpr: -------------------------------------------------------------------------------- 1 | program Example1; 2 | 3 | uses 4 | Forms, 5 | Example1.Form in 'Example1.Form.pas' {Form1}, 6 | urs.DataSetHelper in '..\source\urs.DataSetHelper.pas'; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.MainFormOnTaskbar := True; 13 | Application.CreateForm(TForm1, Form1); 14 | Application.Run; 15 | end. 16 | -------------------------------------------------------------------------------- /examples/Example1.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {5DB61331-EF6C-4931-8415-34BAF882703E} 4 | Example1.dpr 5 | True 6 | Debug 7 | 1 8 | Application 9 | VCL 10 | 18.8 11 | Win32 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Cfg_1 34 | true 35 | true 36 | 37 | 38 | true 39 | Base 40 | true 41 | 42 | 43 | true 44 | Cfg_2 45 | true 46 | true 47 | 48 | 49 | false 50 | false 51 | false 52 | false 53 | false 54 | 00400000 55 | Example1 56 | Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 57 | 1031 58 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= 59 | 60 | 61 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 62 | Debug 63 | true 64 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 65 | 1033 66 | $(BDS)\bin\default_app.manifest 67 | true 68 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 69 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 70 | 71 | 72 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 73 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 74 | 75 | 76 | RELEASE;$(DCC_Define) 77 | 0 78 | false 79 | 0 80 | 81 | 82 | true 83 | PerMonitorV2 84 | 85 | 86 | DEBUG;$(DCC_Define) 87 | false 88 | true 89 | 90 | 91 | true 92 | PerMonitorV2 93 | 94 | 95 | 96 | MainSource 97 | 98 | 99 |
Form1
100 |
101 | 102 | 103 | Cfg_2 104 | Base 105 | 106 | 107 | Base 108 | 109 | 110 | Cfg_1 111 | Base 112 | 113 |
114 | 115 | Delphi.Personality.12 116 | 117 | 118 | 119 | 120 | Example1.dpr 121 | 122 | 123 | 124 | True 125 | False 126 | 127 | 128 | 129 | 130 | Example1.exe 131 | true 132 | 133 | 134 | 135 | 136 | 1 137 | 138 | 139 | Contents\MacOS 140 | 1 141 | 142 | 143 | 0 144 | 145 | 146 | 147 | 148 | classes 149 | 1 150 | 151 | 152 | classes 153 | 1 154 | 155 | 156 | 157 | 158 | res\xml 159 | 1 160 | 161 | 162 | res\xml 163 | 1 164 | 165 | 166 | 167 | 168 | library\lib\armeabi-v7a 169 | 1 170 | 171 | 172 | 173 | 174 | library\lib\armeabi 175 | 1 176 | 177 | 178 | library\lib\armeabi 179 | 1 180 | 181 | 182 | 183 | 184 | library\lib\armeabi-v7a 185 | 1 186 | 187 | 188 | 189 | 190 | library\lib\mips 191 | 1 192 | 193 | 194 | library\lib\mips 195 | 1 196 | 197 | 198 | 199 | 200 | library\lib\armeabi-v7a 201 | 1 202 | 203 | 204 | library\lib\arm64-v8a 205 | 1 206 | 207 | 208 | 209 | 210 | library\lib\armeabi-v7a 211 | 1 212 | 213 | 214 | 215 | 216 | res\drawable 217 | 1 218 | 219 | 220 | res\drawable 221 | 1 222 | 223 | 224 | 225 | 226 | res\values 227 | 1 228 | 229 | 230 | res\values 231 | 1 232 | 233 | 234 | 235 | 236 | res\values-v21 237 | 1 238 | 239 | 240 | res\values-v21 241 | 1 242 | 243 | 244 | 245 | 246 | res\values 247 | 1 248 | 249 | 250 | res\values 251 | 1 252 | 253 | 254 | 255 | 256 | res\drawable 257 | 1 258 | 259 | 260 | res\drawable 261 | 1 262 | 263 | 264 | 265 | 266 | res\drawable-xxhdpi 267 | 1 268 | 269 | 270 | res\drawable-xxhdpi 271 | 1 272 | 273 | 274 | 275 | 276 | res\drawable-ldpi 277 | 1 278 | 279 | 280 | res\drawable-ldpi 281 | 1 282 | 283 | 284 | 285 | 286 | res\drawable-mdpi 287 | 1 288 | 289 | 290 | res\drawable-mdpi 291 | 1 292 | 293 | 294 | 295 | 296 | res\drawable-hdpi 297 | 1 298 | 299 | 300 | res\drawable-hdpi 301 | 1 302 | 303 | 304 | 305 | 306 | res\drawable-xhdpi 307 | 1 308 | 309 | 310 | res\drawable-xhdpi 311 | 1 312 | 313 | 314 | 315 | 316 | res\drawable-mdpi 317 | 1 318 | 319 | 320 | res\drawable-mdpi 321 | 1 322 | 323 | 324 | 325 | 326 | res\drawable-hdpi 327 | 1 328 | 329 | 330 | res\drawable-hdpi 331 | 1 332 | 333 | 334 | 335 | 336 | res\drawable-xhdpi 337 | 1 338 | 339 | 340 | res\drawable-xhdpi 341 | 1 342 | 343 | 344 | 345 | 346 | res\drawable-xxhdpi 347 | 1 348 | 349 | 350 | res\drawable-xxhdpi 351 | 1 352 | 353 | 354 | 355 | 356 | res\drawable-xxxhdpi 357 | 1 358 | 359 | 360 | res\drawable-xxxhdpi 361 | 1 362 | 363 | 364 | 365 | 366 | res\drawable-small 367 | 1 368 | 369 | 370 | res\drawable-small 371 | 1 372 | 373 | 374 | 375 | 376 | res\drawable-normal 377 | 1 378 | 379 | 380 | res\drawable-normal 381 | 1 382 | 383 | 384 | 385 | 386 | res\drawable-large 387 | 1 388 | 389 | 390 | res\drawable-large 391 | 1 392 | 393 | 394 | 395 | 396 | res\drawable-xlarge 397 | 1 398 | 399 | 400 | res\drawable-xlarge 401 | 1 402 | 403 | 404 | 405 | 406 | res\values 407 | 1 408 | 409 | 410 | res\values 411 | 1 412 | 413 | 414 | 415 | 416 | 1 417 | 418 | 419 | Contents\MacOS 420 | 1 421 | 422 | 423 | 0 424 | 425 | 426 | 427 | 428 | Contents\MacOS 429 | 1 430 | .framework 431 | 432 | 433 | Contents\MacOS 434 | 1 435 | .framework 436 | 437 | 438 | 0 439 | 440 | 441 | 442 | 443 | 1 444 | .dylib 445 | 446 | 447 | 1 448 | .dylib 449 | 450 | 451 | 1 452 | .dylib 453 | 454 | 455 | Contents\MacOS 456 | 1 457 | .dylib 458 | 459 | 460 | Contents\MacOS 461 | 1 462 | .dylib 463 | 464 | 465 | 0 466 | .dll;.bpl 467 | 468 | 469 | 470 | 471 | 1 472 | .dylib 473 | 474 | 475 | 1 476 | .dylib 477 | 478 | 479 | 1 480 | .dylib 481 | 482 | 483 | Contents\MacOS 484 | 1 485 | .dylib 486 | 487 | 488 | Contents\MacOS 489 | 1 490 | .dylib 491 | 492 | 493 | 0 494 | .bpl 495 | 496 | 497 | 498 | 499 | 0 500 | 501 | 502 | 0 503 | 504 | 505 | 0 506 | 507 | 508 | 0 509 | 510 | 511 | 0 512 | 513 | 514 | Contents\Resources\StartUp\ 515 | 0 516 | 517 | 518 | Contents\Resources\StartUp\ 519 | 0 520 | 521 | 522 | 0 523 | 524 | 525 | 526 | 527 | 1 528 | 529 | 530 | 1 531 | 532 | 533 | 1 534 | 535 | 536 | 537 | 538 | 1 539 | 540 | 541 | 1 542 | 543 | 544 | 1 545 | 546 | 547 | 548 | 549 | 1 550 | 551 | 552 | 1 553 | 554 | 555 | 1 556 | 557 | 558 | 559 | 560 | 1 561 | 562 | 563 | 1 564 | 565 | 566 | 1 567 | 568 | 569 | 570 | 571 | 1 572 | 573 | 574 | 1 575 | 576 | 577 | 1 578 | 579 | 580 | 581 | 582 | 1 583 | 584 | 585 | 1 586 | 587 | 588 | 1 589 | 590 | 591 | 592 | 593 | 1 594 | 595 | 596 | 1 597 | 598 | 599 | 1 600 | 601 | 602 | 603 | 604 | 1 605 | 606 | 607 | 1 608 | 609 | 610 | 1 611 | 612 | 613 | 614 | 615 | 1 616 | 617 | 618 | 1 619 | 620 | 621 | 1 622 | 623 | 624 | 625 | 626 | 1 627 | 628 | 629 | 1 630 | 631 | 632 | 1 633 | 634 | 635 | 636 | 637 | 1 638 | 639 | 640 | 1 641 | 642 | 643 | 1 644 | 645 | 646 | 647 | 648 | 1 649 | 650 | 651 | 1 652 | 653 | 654 | 1 655 | 656 | 657 | 658 | 659 | 1 660 | 661 | 662 | 1 663 | 664 | 665 | 1 666 | 667 | 668 | 669 | 670 | 1 671 | 672 | 673 | 1 674 | 675 | 676 | 1 677 | 678 | 679 | 680 | 681 | 1 682 | 683 | 684 | 1 685 | 686 | 687 | 1 688 | 689 | 690 | 691 | 692 | 1 693 | 694 | 695 | 1 696 | 697 | 698 | 1 699 | 700 | 701 | 702 | 703 | 1 704 | 705 | 706 | 1 707 | 708 | 709 | 1 710 | 711 | 712 | 713 | 714 | 1 715 | 716 | 717 | 1 718 | 719 | 720 | 1 721 | 722 | 723 | 724 | 725 | 1 726 | 727 | 728 | 1 729 | 730 | 731 | 1 732 | 733 | 734 | 735 | 736 | 1 737 | 738 | 739 | 1 740 | 741 | 742 | 1 743 | 744 | 745 | 746 | 747 | 1 748 | 749 | 750 | 1 751 | 752 | 753 | 1 754 | 755 | 756 | 757 | 758 | 1 759 | 760 | 761 | 1 762 | 763 | 764 | 1 765 | 766 | 767 | 768 | 769 | 1 770 | 771 | 772 | 1 773 | 774 | 775 | 1 776 | 777 | 778 | 779 | 780 | 1 781 | 782 | 783 | 1 784 | 785 | 786 | 1 787 | 788 | 789 | 790 | 791 | 1 792 | 793 | 794 | 1 795 | 796 | 797 | 798 | 799 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 800 | 1 801 | 802 | 803 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 804 | 1 805 | 806 | 807 | 808 | 809 | 1 810 | 811 | 812 | 1 813 | 814 | 815 | 816 | 817 | ..\ 818 | 1 819 | 820 | 821 | ..\ 822 | 1 823 | 824 | 825 | 826 | 827 | 1 828 | 829 | 830 | 1 831 | 832 | 833 | 1 834 | 835 | 836 | 837 | 838 | 1 839 | 840 | 841 | 1 842 | 843 | 844 | 1 845 | 846 | 847 | 848 | 849 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 850 | 1 851 | 852 | 853 | 854 | 855 | ..\ 856 | 1 857 | 858 | 859 | ..\ 860 | 1 861 | 862 | 863 | 864 | 865 | Contents 866 | 1 867 | 868 | 869 | Contents 870 | 1 871 | 872 | 873 | 874 | 875 | Contents\Resources 876 | 1 877 | 878 | 879 | Contents\Resources 880 | 1 881 | 882 | 883 | 884 | 885 | library\lib\armeabi-v7a 886 | 1 887 | 888 | 889 | library\lib\arm64-v8a 890 | 1 891 | 892 | 893 | 1 894 | 895 | 896 | 1 897 | 898 | 899 | 1 900 | 901 | 902 | 1 903 | 904 | 905 | Contents\MacOS 906 | 1 907 | 908 | 909 | Contents\MacOS 910 | 1 911 | 912 | 913 | 0 914 | 915 | 916 | 917 | 918 | library\lib\armeabi-v7a 919 | 1 920 | 921 | 922 | 923 | 924 | 1 925 | 926 | 927 | 1 928 | 929 | 930 | 931 | 932 | Assets 933 | 1 934 | 935 | 936 | Assets 937 | 1 938 | 939 | 940 | 941 | 942 | Assets 943 | 1 944 | 945 | 946 | Assets 947 | 1 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 12 963 | 964 | 965 | 966 | 967 |
968 | -------------------------------------------------------------------------------- /source/urs.DataSetHelper.pas: -------------------------------------------------------------------------------- 1 | unit urs.DataSetHelper; 2 | 3 | interface 4 | 5 | uses 6 | System.Rtti, System.Generics.Collections, 7 | Data.DB; 8 | 9 | type 10 | TDBFieldsMapping = (mapAuto, mapManual); 11 | 12 | var 13 | DefaultDBFieldsMapping: TDBFieldsMapping = mapAuto; 14 | 15 | type 16 | DBFieldsAttribute = class(TCustomAttribute) 17 | strict protected 18 | FMode: TDBFieldsMapping; 19 | public 20 | constructor Create(AMode: TDBFieldsMapping); 21 | property Mode: TDBFieldsMapping read FMode; 22 | end; 23 | 24 | DBFieldAttribute = class(TCustomAttribute) 25 | strict protected 26 | FIsStored: Boolean; 27 | FFieldName: String; 28 | public 29 | constructor Create; overload; 30 | constructor Create(const AIsStored: Boolean); overload; 31 | constructor Create(const AFieldName: string); overload; 32 | property IsStored: Boolean read FIsStored; 33 | property FieldName: String read FFieldName; 34 | end; 35 | 36 | TDataSetHelper = class helper for TDataSet 37 | private type 38 | TDataSetRecord = class 39 | private type 40 | TMapping = class 41 | private 42 | FField: TField; 43 | FIsInstanceType: Boolean; 44 | protected 45 | function GetPointer(var Target: T): Pointer; 46 | property IsInstanceType: Boolean read FIsInstanceType; 47 | public 48 | constructor Create(AField: TField; AIsInstanceType: Boolean); 49 | procedure LoadFromField(var Target: T); virtual; abstract; 50 | procedure StoreToField(var Source: T); virtual; abstract; 51 | end; 52 | 53 | TFieldMapping = class(TMapping) 54 | private 55 | FRTTIField: TRTTIField; 56 | public 57 | constructor Create(AField: TField; ARTTIField: TRTTIField; AIsInstanceType: Boolean); 58 | procedure StoreToField(var Source: T); override; 59 | procedure LoadFromField(var Target: T); override; 60 | end; 61 | 62 | TPropMapping = class(TMapping) 63 | private 64 | FRTTIProp: TRttiProperty; 65 | public 66 | constructor Create(AField: TField; ARTTIProp: TRttiProperty; AIsInstanceType: Boolean); 67 | procedure StoreToField(var Source: T); override; 68 | procedure LoadFromField(var Target: T); override; 69 | end; 70 | 71 | private 72 | FDataSet: TDataSet; 73 | FInstance: T; 74 | FMapMode: TDBFieldsMapping; 75 | FMappings: TObjectList; 76 | FRTTIContext: TRTTIContext; 77 | function CheckAttributes(obj: TRttiNamedObject): string; 78 | function GetCurrent: T; 79 | function GetMapMode(obj: TRttiNamedObject): TDBFieldsMapping; 80 | procedure LoadMappings; 81 | protected 82 | procedure Initialize; virtual; 83 | property Instance: T read FInstance; 84 | public 85 | constructor Create(ADataSet: TDataSet); overload; 86 | constructor Create(ADataSet: TDataSet; const AInstance: T); overload; 87 | destructor Destroy; override; 88 | procedure LoadFromCurrent(var Target: T); 89 | procedure StoreToCurrent(var Source: T); 90 | property Current: T read GetCurrent; 91 | end; 92 | 93 | TDataSetEnumerator = class(TDataSetRecord) 94 | private 95 | FBookmark: TBookmark; 96 | FMoveToFirst: Boolean; 97 | FWasActive: Boolean; 98 | protected 99 | procedure Initialize; override; 100 | public 101 | destructor Destroy; override; 102 | function MoveNext: Boolean; 103 | end; 104 | 105 | IRecords = interface 106 | function GetEnumerator: TDataSetEnumerator; 107 | end; 108 | 109 | TRecords = class(TInterfacedObject, IRecords) 110 | private 111 | FDataSet: TDataSet; 112 | public 113 | constructor Create(ADataSet: TDataSet); 114 | function GetEnumerator: TDataSetEnumerator; virtual; 115 | end; 116 | 117 | TRecordsInstance = class(TRecords) 118 | private 119 | FInstance: T; 120 | public 121 | constructor Create(ADataSet: TDataSet; AInstance: T); 122 | function GetEnumerator: TDataSetEnumerator; override; 123 | end; 124 | 125 | public 126 | function GetCurrentRec: T; 127 | procedure SetCurrentRec(AInstance: T); 128 | procedure LoadInstanceFromCurrent(AInstance: T); 129 | procedure StoreInstanceToCurrent(AInstance: T); 130 | function Records(AInstance: T): IRecords; overload; 131 | function Records: IRecords; overload; 132 | end; 133 | 134 | implementation 135 | 136 | uses 137 | System.Sysutils; 138 | 139 | constructor DBFieldsAttribute.Create(AMode: TDBFieldsMapping); 140 | begin 141 | inherited Create; 142 | FMode := AMode; 143 | end; 144 | 145 | constructor DBFieldAttribute.Create; 146 | begin 147 | inherited Create; 148 | FIsStored := true; 149 | FFieldName := ''; 150 | end; 151 | 152 | constructor DBFieldAttribute.Create(const AIsStored: Boolean); 153 | begin 154 | inherited Create; 155 | FIsStored := AIsStored; 156 | FFieldName := ''; 157 | end; 158 | 159 | constructor DBFieldAttribute.Create(const AFieldName: string); 160 | begin 161 | inherited Create; 162 | FIsStored := true; 163 | FFieldName := AFieldName; 164 | end; 165 | 166 | procedure TDataSetHelper.LoadInstanceFromCurrent(AInstance: T); 167 | var 168 | tmp: TDataSetRecord; 169 | begin 170 | tmp := TDataSetRecord.Create(Self, AInstance); 171 | try 172 | tmp.LoadFromCurrent(AInstance); 173 | finally 174 | tmp.Free; 175 | end; 176 | end; 177 | 178 | function TDataSetHelper.GetCurrentRec: T; 179 | var 180 | tmp: TDataSetRecord; 181 | begin 182 | tmp := TDataSetRecord.Create(Self); 183 | try 184 | result := tmp.Current; 185 | finally 186 | tmp.Free; 187 | end; 188 | end; 189 | 190 | procedure TDataSetHelper.StoreInstanceToCurrent(AInstance: T); 191 | var 192 | tmp: TDataSetRecord; 193 | begin 194 | tmp := TDataSetRecord.Create(Self, AInstance); 195 | try 196 | tmp.StoreToCurrent(AInstance); 197 | finally 198 | tmp.Free; 199 | end; 200 | end; 201 | 202 | function TDataSetHelper.Records(AInstance: T): IRecords; 203 | begin 204 | Result := TRecordsInstance.Create(Self, AInstance); 205 | end; 206 | 207 | function TDataSetHelper.Records: IRecords; 208 | begin 209 | Result := TRecords.Create(Self); 210 | end; 211 | 212 | procedure TDataSetHelper.SetCurrentRec(AInstance: T); 213 | var 214 | tmp: TDataSetRecord; 215 | begin 216 | tmp := TDataSetRecord.Create(Self, AInstance); 217 | try 218 | tmp.StoreToCurrent(AInstance); 219 | finally 220 | tmp.Free; 221 | end; 222 | end; 223 | 224 | destructor TDataSetHelper.TDataSetEnumerator.Destroy; 225 | { Restore the DataSet to its previous state. } 226 | begin 227 | if FWasActive then begin 228 | { if we have a valid bookmark, use it } 229 | if FDataSet.BookmarkValid(FBookmark) then 230 | FDataSet.GotoBookmark(FBookmark); 231 | { I'm not sure, if FreeBokmark can handle nil pointers - so to be safe } 232 | if FBookmark <> nil then 233 | FDataSet.FreeBookmark(FBookmark); 234 | end 235 | else 236 | FDataSet.Active := false; 237 | { don't forget this one! } 238 | FDataSet.EnableControls; 239 | inherited; 240 | end; 241 | 242 | constructor TDataSetHelper.TDataSetRecord.Create(ADataSet: TDataSet); 243 | begin 244 | Create(ADataSet, Default(T)); 245 | end; 246 | 247 | constructor TDataSetHelper.TDataSetRecord.Create(ADataSet: TDataSet; const AInstance: T); 248 | begin 249 | inherited Create; 250 | FDataSet := ADataSet; 251 | FInstance := AInstance; 252 | Initialize; 253 | end; 254 | 255 | destructor TDataSetHelper.TDataSetRecord.Destroy; 256 | begin 257 | FMappings.Free; 258 | inherited; 259 | end; 260 | 261 | function TDataSetHelper.TDataSetRecord.CheckAttributes(obj: TRttiNamedObject): string; 262 | var 263 | attr: TCustomAttribute; 264 | storedAttr: DBFieldAttribute; 265 | begin 266 | case FMapMode of 267 | mapAuto: result := obj.Name; 268 | mapManual: result := ''; 269 | end; 270 | for attr in obj.GetAttributes do begin 271 | if attr is DBFieldAttribute then begin 272 | storedAttr := attr as DBFieldAttribute; 273 | if storedAttr.IsStored then begin 274 | if storedAttr.FieldName > '' then begin 275 | Result := storedAttr.FieldName; 276 | end; 277 | end 278 | else begin 279 | Result := ''; 280 | end; 281 | Break; 282 | end; 283 | end; 284 | end; 285 | 286 | function TDataSetHelper.TDataSetRecord.GetCurrent: T; 287 | begin 288 | Result := Instance; 289 | LoadFromCurrent(Result); 290 | end; 291 | 292 | function TDataSetHelper.TDataSetRecord.GetMapMode(obj: TRttiNamedObject): TDBFieldsMapping; 293 | var 294 | attr: TCustomAttribute; 295 | begin 296 | result := DefaultDBFieldsMapping; 297 | for attr in obj.GetAttributes do begin 298 | if attr is DBFieldsAttribute then begin 299 | Exit((attr as DBFieldsAttribute).Mode); 300 | end; 301 | end; 302 | end; 303 | 304 | procedure TDataSetHelper.TDataSetRecord.Initialize; 305 | begin 306 | LoadMappings; 307 | end; 308 | 309 | procedure TDataSetHelper.TDataSetRecord.LoadFromCurrent(var Target: T); 310 | var 311 | mapping: TMapping; 312 | begin 313 | for mapping in FMappings do begin 314 | mapping.LoadFromField(Target); 315 | end; 316 | end; 317 | 318 | procedure TDataSetHelper.TDataSetRecord.LoadMappings; 319 | var 320 | field: TRttiField; 321 | fld: TField; 322 | prop: TRttiProperty; 323 | rttyType: TRTTIType; 324 | begin 325 | FMappings := TObjectList.Create; 326 | FRTTIContext := TRTTIContext.Create; 327 | rttyType := FRTTIContext.GetType(TypeInfo(T)); 328 | if rttyType.IsRecord then begin 329 | FInstance := Default(T); 330 | end 331 | else if rttyType.IsInstance then begin 332 | if TValue.From(Instance).AsObject = nil then begin 333 | raise Exception.Create('No instance provided'); 334 | end; 335 | end 336 | else begin 337 | raise Exception.Create('Only records and classes allowed'); 338 | end; 339 | FMapMode := GetMapMode(rttyType); 340 | for field in rttyType.GetFields do begin 341 | fld := FDataSet.FindField(CheckAttributes(field)); 342 | if fld = nil then Continue; 343 | FMappings.Add(TFieldMapping.Create(fld, field, rttyType.IsInstance)); 344 | end; 345 | for prop in rttyType.GetProperties do begin 346 | fld := FDataSet.FindField(CheckAttributes(prop)); 347 | if fld = nil then Continue; 348 | FMappings.Add(TPropMapping.Create(fld, prop, rttyType.IsInstance)); 349 | end; 350 | end; 351 | 352 | procedure TDataSetHelper.TDataSetRecord.StoreToCurrent(var Source: T); 353 | var 354 | mapping: TMapping; 355 | begin 356 | for mapping in FMappings do begin 357 | mapping.StoreToField(Source); 358 | end; 359 | end; 360 | 361 | procedure TDataSetHelper.TDataSetEnumerator.Initialize; 362 | { The enumerator is automatically created and destroyed in the for-in loop. 363 | So we remember the active state and set a flag that the first MoveNext will 364 | not move to the next record, but stays on the first one instead. } 365 | begin 366 | { save the Active state } 367 | FWasActive := FDataSet.Active; 368 | { avoid flickering } 369 | FDataSet.DisableControls; 370 | if FWasActive then begin 371 | { get a bookmark of the Current position - even if it is invalid } 372 | FBookmark := FDataSet.GetBookmark; 373 | FDataSet.First; 374 | end 375 | else begin 376 | { FBookmark is initialized to nil anyway, so no need to set it here } 377 | FDataSet.Active := true; 378 | end; 379 | FMoveToFirst := true; 380 | inherited; 381 | end; 382 | 383 | function TDataSetHelper.TDataSetEnumerator.MoveNext: Boolean; 384 | begin 385 | { Check if we have to move to the first record, which has been done already 386 | during Create. } 387 | if FMoveToFirst then 388 | FMoveToFirst := false 389 | else 390 | FDataSet.Next; 391 | Result := not FDataSet.EoF; 392 | end; 393 | 394 | constructor TDataSetHelper.TRecords.Create(ADataSet: TDataSet); 395 | begin 396 | inherited Create; 397 | FDataSet := ADataSet; 398 | end; 399 | 400 | function TDataSetHelper.TRecords.GetEnumerator: TDataSetEnumerator; 401 | begin 402 | Result := TDataSetEnumerator.Create(FDataSet); 403 | end; 404 | 405 | constructor TDataSetHelper.TDataSetRecord.TMapping.Create(AField: TField; AIsInstanceType: Boolean); 406 | begin 407 | inherited Create; 408 | FField := AField; 409 | FIsInstanceType := AIsInstanceType; 410 | end; 411 | 412 | function TDataSetHelper.TDataSetRecord.TMapping.GetPointer(var Target: T): Pointer; 413 | begin 414 | if IsInstanceType then begin 415 | result := TValue.From(Target).AsObject; 416 | end 417 | else begin 418 | result := @Target; 419 | end; 420 | end; 421 | 422 | constructor TDataSetHelper.TDataSetRecord.TFieldMapping.Create(AField: TField; ARTTIField: TRTTIField; 423 | AIsInstanceType: Boolean); 424 | begin 425 | inherited Create(AField, AIsInstanceType); 426 | FRTTIField := ARTTIField; 427 | end; 428 | 429 | procedure TDataSetHelper.TDataSetRecord.TFieldMapping.LoadFromField(var Target: T); 430 | var 431 | val: TValue; 432 | begin 433 | if FField.IsNull then 434 | val := TValue.Empty 435 | else 436 | val := TValue.FromVariant(FField.Value); 437 | FRTTIField.SetValue(GetPointer(Target), val); 438 | end; 439 | 440 | procedure TDataSetHelper.TDataSetRecord.TFieldMapping.StoreToField(var Source: T); 441 | begin 442 | FField.Value := FRTTIField.GetValue(GetPointer(Source)).AsVariant; 443 | end; 444 | 445 | constructor TDataSetHelper.TDataSetRecord.TPropMapping.Create(AField: TField; ARTTIProp: TRttiProperty; 446 | AIsInstanceType: Boolean); 447 | begin 448 | inherited Create(AField, AIsInstanceType); 449 | FRTTIProp := ARTTIProp; 450 | end; 451 | 452 | procedure TDataSetHelper.TDataSetRecord.TPropMapping.StoreToField(var Source: T); 453 | begin 454 | FField.Value := FRTTIProp.GetValue(GetPointer(Source)).AsVariant; 455 | end; 456 | 457 | procedure TDataSetHelper.TDataSetRecord.TPropMapping.LoadFromField(var Target: T); 458 | var 459 | val: TValue; 460 | begin 461 | if FField.IsNull then 462 | val := TValue.Empty 463 | else 464 | val := TValue.FromVariant(FField.Value); 465 | FRTTIProp.SetValue(GetPointer(Target), val); 466 | end; 467 | 468 | constructor TDataSetHelper.TRecordsInstance.Create(ADataSet: TDataSet; AInstance: T); 469 | begin 470 | inherited Create(ADataSet); 471 | FInstance := AInstance; 472 | end; 473 | 474 | function TDataSetHelper.TRecordsInstance.GetEnumerator: TDataSetEnumerator; 475 | begin 476 | Result := TDataSetEnumerator.Create(FDataSet, FInstance); 477 | end; 478 | 479 | end. 480 | --------------------------------------------------------------------------------