{"id":1494,"date":"2017-07-13T15:05:09","date_gmt":"2017-07-13T13:05:09","guid":{"rendered":"http:\/\/borkedcode.com\/wp\/?p=1494"},"modified":"2017-07-13T15:05:09","modified_gmt":"2017-07-13T13:05:09","slug":"delphi-does-data","status":"publish","type":"post","link":"https:\/\/borkedcode.com\/wp\/?p=1494","title":{"rendered":"Delphi Does Data"},"content":{"rendered":"<p>Delphi<\/p>\n<p>Hi everyone!<\/p>\n<p>Last time we talked Delphi, we talked a bit about frameworks and we built your first Delphi app, a \u201cHello World\u201d for Windows.\u00a0 This time around, we\u2019re going to talk about one of the most common uses for programming tools in business environments \u2013 data access.<\/p>\n<p>Let\u2019s get down to brass tacks on this first \u2013 what is data access?\u00a0 Put simply, \u201cdata access\u201d means the ability of a program to read and write persistent information \u2013 info that will be kept (hopefully safely) while the program is turned off, and can be retrieved when turned on again, or when asked for by another program.\u00a0 Generally, we do this with databases \u2013 things like Oracle, MS SQL, MS Access, etc.<\/p>\n<p>It is also worth making a differentiation between \u201cdata\u201d and \u201cinformation\u201d.\u00a0 In this context, I\u2019m going to use \u201cdata\u201d to represent raw data, the kind of thing that might be useful to a program, but generally doesn\u2019t mean anything to a human who doesn\u2019t know the insides of the computer.\u00a0 \u201cInformation,\u201d on the other hand, I\u2019m going to use to represent the stuff that we can put up in front of a user and have a reasonable chance of being understood.<\/p>\n<p>When Delphi was first launched in 1995, it shipped with a series of VCL components that wrapped up the \u201cBorland Database Engine\u201d (BDE for short), which was already a healthy set of connectors to various databases like Paradox, DBase, DB2, Microsoft SQL Server, Oracle, and a few others (if you count ODBC \u2013 \u201cOpen DataBase Connectivity\u201d, a Microsoft library that enabled vendors to write a connector to ODBC and have coders connect through that \u2013 you could have dozens or hundreds of possibilities).\u00a0 Each of these database types was connected by a library commonly referred to as a \u201cdriver\u201d.\u00a0 So if you had a \u201cdatabase driver\u201d for a specific database, you could access that type of server or group of files.<\/p>\n<p>The basic premise of most data access methods is that a program binds to a general data-access layer library.\u00a0 That library may have one or more drivers (specialist libraries that know how to connect to a specific database type), and each driver knows how to operate with its own specific data repository (be it a SQL server of some sort, or a file-based database like FireFox, Paradox, etc.).<\/p>\n<p>Conceptually, it could look something like this:<\/p>\n<p><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Basic-Data-Architecture.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-medium wp-image-1495\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Basic-Data-Architecture-300x97.jpg\" alt=\"\" width=\"300\" height=\"97\" srcset=\"https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Basic-Data-Architecture-300x97.jpg 300w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Basic-Data-Architecture.jpg 613w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>The job of the programming tool is to make this diagram basically invisible to the programmer (unless he\/she is specifically wanting to write code that does this kind of work.\u00a0 We aren\u2019t doing that, so we want something that encapsulates this sort of function and makes it pretty painless to do.<\/p>\n<p>Fortunately, Delphi was designed almost from the outset to do just that \u2013 and not only to make it painless, but fun.\u00a0 Delphi was the first programming tool to offer its programmers the ability to see live data in its designers as well, which was extremely valuable in making sure one was coding correctly.\u00a0 No one else had ever done it like this, and it was several years before anyone else could offer something similar (a short-lived and extremely bad programming tool called \u201cPowerBuilder\u201d did, and eventually Microsoft figured out a way).<\/p>\n<p>As I mentioned, when Delphi first shipped it had components that wrapped the Borland Database Engine inside it.\u00a0 Since then, quite a few additional \u2018engines\u2019 have been added (I\u2019ll use \u201cengine\u201d to term the library that offers up multiple drivers), expanding Delphi\u2019s potential database access even further.\u00a0 The BDE is still in there, but it is rather old and doesn\u2019t shine quite the way it used to \u2013 it has been deprecated, which in general means it is no longer supported and no new code is being done to improve or expand it.<\/p>\n<p>In addition to BDE, the following engines are included:<\/p>\n<p><strong>Interbase Express<\/strong> \u2013 connectors specific to Interbase, a SQL Server offered by Borland\/Embarcadero\/Idera (I can\u2019t keep straight which company kept what part).\u00a0 Interbase is a fast and compact database that is particularly good for bundling in with applications, though expensive in its deployment costs.<\/p>\n<p><strong>dbExpress<\/strong> \u2013 this is an engine that surfaces drivers for Sybase\u2019s SQL Anywhere, regular Sybase, DB2, Firebird (an open-source fork of Interbase), \u201cIBLite\u201d (an even-more-compact version of Interbase), Informix, Interbase, Microsoft SQL, ODBC, Oracle, and SQLite.\u00a0 It also offers a connection to DataSnap, which is a programming framework for making multi-tiered applications.<\/p>\n<p><strong>DBGo<\/strong> \u2013 components that harness ADO (a successor of sorts to ODBC).<\/p>\n<p><strong>FireDAC<\/strong> \u2013 FireDAC is a modern iteration of the multi-access engines produced in prior generations of programming tools.\u00a0 It presents a common interface to dozens of different data repositories and storage methods.\u00a0 Among them are:<\/p>\n<ul>\n<li>MS Access<\/li>\n<li>MS Excel<\/li>\n<li>DBase<\/li>\n<li>Paradox<\/li>\n<li>FoxPro<\/li>\n<li>ODBC<\/li>\n<li>dbExpress drivers<\/li>\n<li>Ingres<\/li>\n<li>Nexus<\/li>\n<li>DataSnap servers<\/li>\n<li>Firebird (embedded and normal)<\/li>\n<li>MySQL (embedded and normal)<\/li>\n<li>SQLite<\/li>\n<li>MS SQL<\/li>\n<li>MS SQL Azure<\/li>\n<li>MS SQL CE<\/li>\n<li>InterBase ToGo<\/li>\n<li>InterBase<\/li>\n<li>Advantage Database<\/li>\n<li>PostgreSQL<\/li>\n<li>Sybase SQL Anywhere<\/li>\n<li>Informix<\/li>\n<li>Teradata<\/li>\n<li>DB2<\/li>\n<li>Microfocus Cobol<\/li>\n<li>Oracle<\/li>\n<\/ul>\n<p>So\u2026as you can see, FireDAC isn\u2019t joking around.\u00a0 It connects to a LOT of data sources.\u00a0 If yours isn\u2019t listed there, it can probably still be reached through an ODBC driver.\u00a0 (Of course, if it isn\u2019t in there, it probably isn\u2019t worth programming for J.)<\/p>\n<p>Within Delphi, data access is done through a series of components (not necessarily VCL ones, but they all work roughly the same).\u00a0 First, a connector component representing the program\u2019s access to the database server or location is used, and after that one or many components representing the various bundles of data within that location are set up to enable the program to read and write to them.\u00a0 Finally, components responsible for passing that data into visual formats are used, converting the data into information.<\/p>\n<p>In the 10.2 (\u201cTokyo\u201d) build of RAD Studio, the BDE has been removed \u2013 it was deprecated long ago, and finally has been pulled.\u00a0 If you\u2019re maintaining an old version of code that does still contain these, you can retrieve an installer from Embarcadero\u2019s site (here: <a href=\"https:\/\/cc.embarcadero.com\/Item\/30752\">https:\/\/cc.embarcadero.com\/Item\/30752<\/a>), but that\u2019s the only case where I\u2019d recommend you do so.\u00a0 For future use, it\u2019s best to get yourself into one of the more current sets of components.<\/p>\n<p>For starters, let\u2019s take one of the simpler ones, dbExpress, and connect it to a Microsoft SQL Server installation.\u00a0 As it happens, I have a dev edition of MS SQL here on my laptop, so we\u2019ll start with that one.\u00a0 You\u2019re going to need to install at least the MS SQL client software on your system before we get started (the client is also included in the server installation if you\u2019re going to put a full server on your machine).\u00a0 If you\u2019re getting into software development, I\u2019d really recommend you buy a license of the MS SQL Developer Edition (available here:\u00a0 <a href=\"https:\/\/www.microsoft.com\/en-us\/sql-server\/application-development\">https:\/\/www.microsoft.com\/en-us\/sql-server\/application-development<\/a>).\u00a0 It\u2019s a fully-functional server, and is fantastic for working out issues prior to testing against a real server.<\/p>\n<p>Let\u2019s start a new project.\u00a0 You had the basics of this in my last Delphi article, so go ahead and roll one out.\u00a0 A blank form is just fine.\u00a0 I\u2019ll do one here too, a VCL forms app for simplicity\u2019s sake.\u00a0 I\u2019ll target Win64 again as I did previously.<\/p>\n<p>When Delphi was first launched in 1995, people used it a LOT for database access.\u00a0 However, even though the data access components are really small, they tend to collect quickly and can really clutter up your designer.\u00a0 As a solution in Delphi 1, most programmers just added a new form to the project and put all their data components on it to avoid getting their UI out of control.\u00a0 Borland (the original maker of Delphi) recognized this as a pain point right away and in Delphi 2 released what is called a \u201cdata module\u201d \u2013 a non-visible form (so it wouldn\u2019t use as many system resources) which can host all manner of non-visual components like data access stuff, API components, and so on.\u00a0 That\u2019s what we\u2019ll do here too.<\/p>\n<p>Once your project is ready, and you can see your designer with Form1 loaded, go to the File menu.\u00a0 In there choose File &gt; New &gt; Other\u2026 and in the dialog that appears, select \u201cDelphi Files\u201d from the tree view on the left.\u00a0 The right pane will have a list of choices, one of which is \u201cData Module\u201d.\u00a0 Select that and confirm by clicking \u201cOK\u201d.<\/p>\n<div id=\"attachment_1496\" style=\"width: 310px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Data-Module.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1496\" class=\"wp-image-1496 size-medium\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Data-Module-300x228.jpg\" alt=\"\" width=\"300\" height=\"228\" srcset=\"https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Data-Module-300x228.jpg 300w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Data-Module.jpg 725w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1496\" class=\"wp-caption-text\">Thar she blows!<\/p><\/div>\n<p>Notice your Project Manager now shows you have \u201cunit1.pas\u201d and \u201cunit2.pas\u201d as part of your project.\u00a0 Unit1 is your main form, and Unit2 is the datamodule.\u00a0 You should probably save and name your files now, to stay in the habit J.\u00a0 Go ahead, I\u2019ll wait.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Project-Files.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-1500 alignright\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Project-Files.jpg\" alt=\"\" width=\"233\" height=\"186\" \/><\/a>Saved it?\u00a0 Okay, great.\u00a0 Notice the Data Module looks like a blank form, but it has no title bar, no icon, etc.\u00a0 That\u2019s because it will never appear visually within your application.\u00a0 Your visual form will use this Data Module, referencing it so that it can get a grip on the components present within it.\u00a0 To do this, return to your main form, and from the menus choose File &gt; Use Unit.\u00a0 You\u2019ll see a list with your datamodule in it.\u00a0 Double-click and you\u2019re on your way.<\/p>\n<p><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/dbExpress-tools.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-1497\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/dbExpress-tools.jpg\" alt=\"\" width=\"294\" height=\"283\" \/><\/a>First thing we\u2019re going to want is to go to the Tool Palette and open up the \u201cdbExpress\u201d group.\u00a0 The starter is the TSQLConnection, which will represent a persistent connection to our database.\u00a0 Grab one and drop it on your Data Module.\u00a0 The new connection will default to a name of \u201cSQLConnection1\u201d \u2013 go ahead and rename it to \u201cMSSQLConnection\u201d.<\/p>\n<p>Our next step is to designate a driver for this component \u2013 choose \u201cMSSQL\u201d.<\/p>\n<p>By doing this, the component will fill up its \u201cParams\u201d section with a series of values that it will need to operate.\u00a0 Most of these you won\u2019t have to touch or bother with.\u00a0 The two you will need to set are \u201cHostName\u201d and \u201cDatabase\u201d \u2013 the host name will be the name of the server to which you are attaching, and the database is the actual name of the database on that server.\u00a0 For hostname, I could give <a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/MSSQL-Params.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-1499 alignright\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/MSSQL-Params-300x217.jpg\" alt=\"\" width=\"300\" height=\"217\" srcset=\"https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/MSSQL-Params-300x217.jpg 300w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/MSSQL-Params.jpg 450w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>it the full name of my SQL instance (I\u2019m assuming you went and picked up the Dev edition of MS SQL I mentioned above), but since I\u2019ve installed it on my development machine, I can use \u201c.\u201d as the machine name.\u00a0 Each instance of SQL Server gets its own name too, so that is a two-parter.\u00a0 It will look like this:<\/p>\n<p>[MACHINENAME]\\[INSTANCENAME]<\/p>\n<p>So it would look like \u201cMYSYSTEM\\SQLONE\u201d or similar.\u00a0 Since I\u2019m running locally, I\u2019m going to sub \u201c.\u201d for my machine name, so my Servername parameter reads as follows:<\/p>\n<p>.\\THEOSQL<\/p>\n<p>The Database parameter is quite literally the name of the database you intend to connect to (Adventureworks is the sample data that MS has always shipped with their product, so you can test with that, but I\u2019m using a home-grown named \u201cSampleData\u201d).<\/p>\n<p>I\u2019m also going to change my \u201cMaxBlobSize\u201d for my own purposes \u2013 don\u2019t worry about this.\u00a0 Leave yours as -1.\u00a0 If you know what this is for, you can deal with it on your own terms, otherwise it\u2019s not important for this lesson.<\/p>\n<div id=\"attachment_1498\" style=\"width: 260px\" class=\"wp-caption alignright\"><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Finsihed-Params.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1498\" class=\"size-full wp-image-1498\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Finsihed-Params.jpg\" alt=\"\" width=\"250\" height=\"80\" \/><\/a><p id=\"caption-attachment-1498\" class=\"wp-caption-text\">Params, check.<\/p><\/div>\n<p>Once your params are set, you can test them by changing the \u201cConnected\u201d property to \u201ctrue\u201d.\u00a0 You\u2019ll be prompted for a name and password (you did remember to store your login credentials somewhere, didn\u2019t you?), and if you give proper credentials, it\u2019ll change to true.\u00a0 That confirms that you have a live connection to your database.<\/p>\n<p>Once you\u2019ve confirmed this, go ahead and set it back to \u201cfalse\u201d.\u00a0 Leaving a connection on in the designer is setting yourself up for a few problems later, and it\u2019s better to handle it in the program at run-time.\u00a0 We\u2019ll get back to this shortly when I show you how to get live data showing up in your app.<\/p>\n<p>So\u2026we have a connection to the database, but we don\u2019t yet have real data.\u00a0 Let\u2019s set that up next.<\/p>\n<div id=\"attachment_1502\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Table-Contents.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1502\" class=\"size-medium wp-image-1502\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Table-Contents-300x114.jpg\" alt=\"\" width=\"300\" height=\"114\" srcset=\"https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Table-Contents-300x114.jpg 300w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Table-Contents-768x292.jpg 768w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Table-Contents.jpg 889w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1502\" class=\"wp-caption-text\">I made up some data in SQL Server, so we&#8217;ll have something to look at.<\/p><\/div>\n<p>For this, we need a <em>dataset<\/em> component.\u00a0 Where a \u201cconnection\u201d represents a channel to the database server, a \u201cdataset\u201d represents a channel to a specific package of data (which might be the contents of a table, the output of a SQL query, view, or stored procedure, etc. \u2013 basically anything that can be considered to have actual data in it).\u00a0 In the case of dbExpress, this means a TSQLDataSet, TSQLQuery, TSQLStoredProc, TSQLTable, or TSimpleDataSet.\u00a0 Since we\u2019re dealing with MS SQL, let\u2019s keep it straightforward and use a TSQLQuery.\u00a0 This component represents a query you write and store inside the component, and when it is opened, it fires this query off to the server, then makes the response from the server available to your app.<\/p>\n<p>Grab a TSQLQuery and drop it on the datamodule.\u00a0 Rename it from \u201cSQLQuery1\u201d to something more meaningful, like \u2018qryProducts\u2019 (in my case, that\u2019s what I\u2019m doing, because I\u2019ve got some sample data in a \u201cproducts\u201d table).<\/p>\n<p>Check out the properties of your query object.\u00a0 There\u2019s a couple of interesting, and a couple of necessary, elements here.<\/p>\n<p>On the necessary front, \u201cSQLConnection\u201d needs to be set \u2013 because your query needs to know which database to ask for its information.\u00a0 Some apps connect to multiple database servers, or in different ways to the same one (for example, as an admin or as a user) and that would mean multiple connection objects (potentially one object with multiple settings that change at runtime, but it\u2019s easier to manage in code with two separate connection definitions).\u00a0 In our case there\u2019s only one, so click the drop-down in that property and select our connection.<\/p>\n<p>The next and final \u201cnecessary\u201d one is the SQL property.\u00a0 This is a \u201cTStrings\u201d object, which just means it is a list of string values.\u00a0 That list can be a multi-line SQL statement, but we won\u2019t need more than one for this.\u00a0 We\u2019re going to open up the strings editor (click on the ellipsis button in the property), and enter the following SQL statement:<\/p>\n<p>Select * from Products<\/p>\n<p>You can now test this query, by changing the \u201cActive\u201d property from False to True.\u00a0 Again, you\u2019ll be prompted by the program for a username and password (because the query will automatically open the connection, and the connection will want to authenticate you).\u00a0 Once it goes true, set it back to false and set the connection\u2019s \u201cconnected\u201d property back to false as well, because it won\u2019t do that all by itself.<\/p>\n<div id=\"attachment_1501\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Properties-of-qryProducts.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1501\" class=\"size-medium wp-image-1501\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Properties-of-qryProducts-300x228.jpg\" alt=\"\" width=\"300\" height=\"228\" srcset=\"https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Properties-of-qryProducts-300x228.jpg 300w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Properties-of-qryProducts.jpg 493w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1501\" class=\"wp-caption-text\">All set with the query&#8230;<\/p><\/div>\n<p>At this stage we\u2019ve got a connection that can go live, and we\u2019re retrieving data \u2013 so if all we wanted to do was manipulate the data or check a value with our program, we\u2019d be good to go.\u00a0 However, we want to actually show off the information a little bit, so we need some data controls on the main form of our app.<\/p>\n<p>dbExpress is a little quirky, in that it operates on \u201cunidirectional\u201d datasets \u2013 as implied by this sort, it\u2019s a one-way thing.\u00a0 The DBGrid, which we\u2019re going to use shortly, requires a two-way connector.\u00a0 So to get around this, we\u2019re going to insert a little \u201cspoof\u201d on it by pulling our results into a locally-held two-way dataset, called a client dataset.<\/p>\n<p>Although for the purposes of this writeup we\u2019re tricking the dbExpress stuff this way, I need to point out that in a real-world situation the feature that we\u2019re bypassing like this is actually insanely useful.\u00a0 The ClientDataset is designed for creating <em>n-tier<\/em> applications.\u00a0 In the early days, apps were generally \u201cdesktop\u201d and \u201cclient-server\u201d, with workloads either entirely on the single user\u2019s PC, or split between a client and a server.\u00a0 Towards 1997-2000, a revolution happened that added a third option:\u00a0 distributed computing.\u00a0 We look at it now as just the norm, but at the time it was brand new and a very big deal.\u00a0 <em>N-tier<\/em> means splitting your app\u2019s work up among multiple computers (hopefully in a logical fashion) so that more work could be done faster by the app.\u00a0 This later morphed into a wide variety of distributed architectures (like \u201cService Oriented,\u201d etc.), but the premise here is that you\u2019d have a server responsible for hosting persistent data, an app that ran apart from it but which was responsible for retrieving that data (and perhaps performed validations on data sent back to it, etc.), and a client app that not only showed and manipulated that data, but also was able to run in a disconnected environment on a \u201csuitcase\u201d model for the data.\u00a0 When connectivity is re-established, the briefcase ships its changes (called a \u201cdelta packet\u201d) back to the server for handling.<\/p>\n<p>That\u2019s what the ClientDataset does.\u00a0 Very cool component.<\/p>\n<p>Let\u2019s get back to business, though \u2013 to feed data to a ClientDataSet, you need a DatasetProvider.\u00a0 Drop one on your datamodule, and set its name to something that will make sense to you (like \u201cdspProducts\u201d or something).\u00a0 Next set its DataSet property to your query.\u00a0 As you can probably guess, the \u201cDatasetProvider\u201d provides a DataSet to ClientDatasets.\u00a0 Which, surprisingly enough, is what we need next.\u00a0 Go ahead and stick one on the datamodule and set its name to \u201ccdsProducts\u201d.\u00a0 Next set its \u201cProviderName\u201d property to the name of your DatasetProvider, either typing it or via drop-down.<\/p>\n<div id=\"attachment_1503\" style=\"width: 286px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Data-Module-Surface.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1503\" class=\"size-full wp-image-1503\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Data-Module-Surface.jpg\" alt=\"\" width=\"276\" height=\"254\" \/><\/a><p id=\"caption-attachment-1503\" class=\"wp-caption-text\">&#8220;She might not look like much, but she&#8217;s got it where it counts&#8230;&#8221;<\/p><\/div>\n<p>Lastly\u2026<\/p>\n<p>Delphi doesn\u2019t include display elements in its datasets, because the philosophy behind a lot of Delphi programming is \u201cIf you don\u2019t need it, don\u2019t include it.\u201d\u00a0 Datasets are for retrieval and manipulation of data, not its display.\u00a0 To add the ability to display to the mix, you need a component called a TDataSource.<\/p>\n<p>Grab one from the Tool Palette and drop it on the main form of your app.\u00a0 Rename it to \u201cdsProducts\u201d.\u00a0 The job of this component is to relay the data from your datasets to visible data controls on your forms.\u00a0 This control is a bit limited in its scope, but it does have several useful features that when you get into programming seriously, will be extremely handy to have around \u2013 in particular, when a user of your app makes changes to the data in a form, you can insert routines that can look over the changes they are about to make, and perhaps abort them or pause the user if what they are about to enter is questionable or invalid.\u00a0 We won\u2019t get into that here, but just be aware that\u2019s what that component is good for.<\/p>\n<p>Since our main form \u201cuses\u201d the datamodule, it will have visibility on what components are available there \u2013 namely the Query we put on it a few minutes ago.\u00a0 If you go to the Data Source\u2019s \u201cDataSet\u201d property and choose the drop-down, you should see the Query from the datamodule listed there.\u00a0 Select it and let\u2019s move on.<\/p>\n<p>Next thing, let\u2019s keep it basic, will be a DBGrid.\u00a0 A Grid is just a row-by-row display of all the columns in your dataset (the grid itself has a lot of customization features to it as well, but for now we\u2019re going to just make it a clear window on the data).<\/p>\n<p>Slap a DBGrid onto your form, and assign its dataset property to the dataset you created a few moments ago.\u00a0 That\u2019s really all you have to do.<\/p>\n<div id=\"attachment_1504\" style=\"width: 310px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Grid-with-Button.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1504\" class=\"size-medium wp-image-1504\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Grid-with-Button-300x73.jpg\" alt=\"\" width=\"300\" height=\"73\" srcset=\"https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Grid-with-Button-300x73.jpg 300w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Grid-with-Button.jpg 674w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1504\" class=\"wp-caption-text\">Slap-bang on the form<\/p><\/div>\n<p>Ready to test something cool?\u00a0 Set the ClientDataSet\u2019s \u201cactive\u201d property to \u201cTrue\u201d.\u00a0 If everything is wired up properly, the DBGrid will populate with data from your table \u2013 in the designer!\u00a0 It\u2019s able to do that because Delphi\u2019s IDE is, itself, a running Delphi application.\u00a0 This was a <em>huge <\/em>development back when it launched, and for many years afterwards, because there wasn\u2019t any other dev tool that could pull that little trick off.\u00a0 And when you\u2019re building a data-driven user interface, there is nothing better than viewing it with real results.<\/p>\n<div id=\"attachment_1505\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Live-Data-in-Designer.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1505\" class=\"size-medium wp-image-1505\" src=\"http:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Live-Data-in-Designer-300x84.jpg\" alt=\"\" width=\"300\" height=\"84\" srcset=\"https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Live-Data-in-Designer-300x84.jpg 300w, https:\/\/borkedcode.com\/wp\/wp-content\/uploads\/2017\/07\/Live-Data-in-Designer.jpg 660w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1505\" class=\"wp-caption-text\">Ta-da! Yeah, baby!<\/p><\/div>\n<p>Go ahead and set the Active property of both the ClientDataSet and your Query to false again (the CDS will have switched it on) and the Connection\u2019s \u201cConnected\u201d property back to False.<\/p>\n<p>Finally, while we\u2019re in here, let\u2019s put a button next to the grid for turning the data on and off.\u00a0 I\u2019m going to show you something a little bit fancier than our standard controls in how we\u2019re going to write code around that, as well.\u00a0 Instead of writing a control that directly grabs the query and turns it on, we\u2019re going to follow the chain of references in the components.<\/p>\n<p>Once your button is on the form, double-click it to create an \u201cOnClick\u201d event handler.<\/p>\n<p>In that handler, write the following code:<\/p>\n<p>if grdData.DataSource.DataSet.Active then<\/p>\n<p>begin<\/p>\n<p>dmMain.MSSQLConnection.Close;<\/p>\n<p>btnDataToggle.Caption := &#8216;Open Me&#8217;;<\/p>\n<p>end<\/p>\n<p>else begin<\/p>\n<p>grdData.DataSource.DataSet.Open;<\/p>\n<p>btnDataToggle.Caption := &#8216;Close Me&#8217;;<\/p>\n<p>end;<\/p>\n<p>What this translates into is that we are looking at the grid\u2019s datasource, checking its dataset, and if that dataset is currently \u201cActive\u201d (open), we close its connection, closing the dataset too.\u00a0 If it happens to be closed, we open it.\u00a0 In either case, we change the text of the button to represent what pressing it again will do.<\/p>\n<p>You\u2019re all set now \u2013 you can take that executable you just built and use it on pretty much any PC that has a SQL Server client on it, and a valid link back to your chosen server.<\/p>\n<p>Play around with the various kinds of controls here \u2013 there are a great many data-aware elements you can goof around with.\u00a0 For me, I\u2019m going to go for a while, and next time I\u2019ll write up some examples of other methods of accessing data \u2013 ADO and FireDAC.<\/p>\n<p>Until then, have fun!<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Delphi Hi everyone! Last time we talked Delphi, we talked a bit about frameworks and we built your first Delphi app, a \u201cHello World\u201d for Windows.\u00a0 This time around, we\u2019re going to talk about one of the most common uses &hellip; <a href=\"https:\/\/borkedcode.com\/wp\/?p=1494\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[112,30,111,43],"tags":[123,119,118,104,120,121,122],"class_list":["post-1494","post","type-post","status-publish","format-standard","hentry","category-development","category-it","category-programming","category-software","tag-10-2","tag-data","tag-dbexpress","tag-delphi","tag-live-data","tag-ms-sql","tag-tokyo"],"_links":{"self":[{"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/1494","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1494"}],"version-history":[{"count":1,"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/1494\/revisions"}],"predecessor-version":[{"id":1506,"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/1494\/revisions\/1506"}],"wp:attachment":[{"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1494"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1494"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/borkedcode.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1494"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}