I am planning to move away from BDE and dBase so, while implementing some application I need to stay away from everything that could make the transition more difficult. I wonder, for instance, if data aware components like TDBCtrlGrid is toot tied in some way to the BDE or not.
Db-aware components like the TDBCtrlGrid, TDBGrid, TDBEdit, etc, should all work fine with more modern TDataSet-descendants than TQuery, TTable, etc. So the answer to your q is that they are all generic.
The whole point of the design of Delphi's db-aware components is that the access model they use is abstracted from any particular dataset implementation and so will work with any TDataSet descendant, because TDataSet itself implements an abstracted data-access model.
Delphi's db-aware components work at two steps removed from TDataSet, and interact with it (or any descendant of it) via TDataSource and TDataLink and its descendants. All data interactions occur via TDataLinks - see the source in DB.Pas.
Short answer is no : TDBCtrlGrid is not tied to the BDE.
TDBCtrlGrid is populated by a "dataset" or, if you prefer, by a TDataSet which is an abstract class providing the basic properties, events, and methods for working with data.
There are many implementations of TDataSet which will allow you to use whatever data base engine you want.
From the doc here are some popular TDataSet implementations :
TCustomADODataSet is the base class for datasets that access their
data using ActiveX Data Objects (ADO). TCustomADODataSet descendants
include TADODataSet, TADOTable, TADOQuery, and TADOStoredProc.
Developers who create custom dataset components that use ADO derive
them from CustomADODataSet.
TIBCustomDataSet is the base class for datasets that directly access
the data in InterBase tables. TIBCustomDataSet descendants include
TIBDataSet, TIBTable, TIBQuery, and TIBStoredProc. Developers who
create custom dataset components that directly access data in an
InterBase database derive from TIBCustomDataSet.
TCustomSQLDataSet is the base class for unidirectional datasets.
Unidirectional datasets are read-only datasets that permit only
forward navigation. TCustomSQLDataSet descendants include the
dbExpress datasets TSQLDataSet, TSQLQuery, TSQLTable, and
TSQLStoredProc. Developers who create custom dataset components that
use dbExpress to access their data derive from TCustomSQLDataSet.
TCustomClientDataSet is the base class for in-memory datasets. Client
datasets can work with data from files on disk or with data provided
by another component via a provider. They cache that data in memory,
maintain a record of any changes in a change log, and apply cached
updates at a later point back to the source of the data. Developers
who create custom datasets that store their data in an in-memory cache
derive from TCustomClientDataSet.
I would investigate several databases including some of the latest in the Delphi version you currently use. That includes Mongo if you have the latest.
For productivity Firedac is quite good. It codes like ADO and performs almost as well as GO.
In general I suggest getting Nick Hodges' book and start using Spring4D.
If that is too deep for you then Firedac is a good starting point.
Related
What is the purpose of having a DataModule in your project? Does it have any special properties compared to a normal class or module? What are the conventions of what it's usually used for?
A datamodule is a non-visual "form" (container) that can contain non-visual components (usually database components, though any component can be added, such as dialogs and Indy components) that can then be shared by many forms.
This wiki explains further: Delphi Wikki.
It is normally used for Dataset and DataSource objects to keep them in a central location. A DataModule can only contain nonvisual components on it but are not just limited to Data Access components. You could put a TTimer on it and SaveDialog etc...
It can be useful when you have multiple forms, needing to change the code only in one place, instead of every form.
A datamodule differs from a simple class that it can be designed within the form designer and its components can be edited with the object inspector. The datamodule has also a resource that is streamed in a DFM file.
Furthermore a datamodule can be used by other datamodules, forms and frames and then its components are available for selection in the object inspector, too.
In my desktop applications, I usually have one data module containing a bunch of TImageLists. If my applications uses TCP/IP, the components are on a separate data module. Of course almost all of my application's logic goes in different data modules. And, if I need to create a service application, I put my logic in a data module so that I can easily create a desktop application around it for debugging. And, last, but least, I put my data access components on data modules most of the time.
I would persuade a friend me that using Using Database Components (DB Aware Controls) in Delphi is by far the best option, when developing database applications.
This debated started with him many years ago: still today he is persuaded that using simple controls like TEdit, TStringGrid etc., with a set of getter and setter methods to populate them, is the best solution both in terms of flexibility and maintainability of the whole project.
To me this sound counter-intuitive at least.
I think that using DB Aware Controls, like TDBEdit, TDBGrid etc. is the right thing to do when developing database applications.
So: please help me convince him with sound advises about using DB Aware Controls!
Thank you in advance to all of you that will post at least his own advice, whatever will be in favor of one or the other solution.
--
fabio vitale
DB-Aware vs non DB-Aware is kind of a obsolete discussion. DB-Aware controls have automatic databinding, which means they autofills themself with data, do change detection and write to the members of the datasource bounded; in non-dbaware controls, it's up to you to do those tasks. This can lead to messy code too - or overengineered frameworks just to do databinding. Both scenarios are bad.
The kind of datasource and the quality of the individual control will determine the performance. I've seen a lot of code to databind TStringGrid simply just to avoid TDBGrid because of purism (when TDbGrid would do nicely) - just a overly absurd loss of time.
It became an obsolete discussion when TClientDataset became the de-facto dataset for disconnected applications: you can pull data, disconnect, work on data, connect again and apply changes. Since CDS+DbAware controls will do 99% of the interface, you use the non-data-aware controls for the next 1% (for some complex interfaces).
I still don't have XE2 to see if LiveBindings do the OO databinding work nicely - if so, now all controls can db-aware if needed.
EDIT: in da-soft's answer, he(she?) argues that DbAware controls implements MVC pattern and LachlanG disagrees that, even it does, doesn't that code itself is MVC. I'll give my $0,02 cents here ;-)
I think that the use of a 1:1 relation in DataModule and Entity (as in ERD) - or DataModule and a Form - you can get an application where responsibilities are separated:
form dfm -> Layout and design-time databinding (have only Datasources)
form *.pas -> controls interface and asks Data Module for data (acts like a controller)
Data Module -> methods to answer forms requests for data retrieval
and data updates
I normally have an separated data module for database connection which is passed through forms/entities' properties.
DB-aware controls pros:
The work to load data to a control and save data to a dataset is performed by VCL. You have less to code - really RAD.
The DB-aware controls + TDataSource + TDataSet implements MVC pattern. That helps to separate GUI and data access code.
The code validating, reformating, doing other post processing of the data will be called in well defined moments using event handlers. That helps to centralize such code and avoid confusions with the places where it should be placed. And avoid confusions with the moments when to call it.
Cons:
This is not a universal approach. You cannot bind a DB-aware control to a non-TDataSet data source. This issue was solved with introducing Live Data Binding in Delphi XE2.
Event driven programming may be confusing for some developers. And requires knowledge of TDataSource, TDataSet, TField events and architecture, and lead to controversy with Pros (3). Bad event driven code may be nightmare.
Both DB-aware and non-DB-aware components have advantages and disadvantages, depending on what kind of application you are developing.
For small-to-middle scale applications, using DB-aware components is encouraged, unless there are specific requirements or conditions under which those applications are operating. For example, a simple data entry application would be easier to develop and maintain with DB-aware components. Even middle-to-large scale applications, if properly designed and implemented, will have good performance with DB-aware components.
However, when developing modular applications, especially multi-tier systems, DB-aware components can have negative impact on application performance and maintainability. This is particularly noticeable with applications that access data over the Internet. Main reason for this is because DB-aware components require a constant connection to the database, which can significantly increase network traffic.
Using non-DB-aware components can be more complex since it requires better understanding of the underlying mechanisms, but in multi-user and distributed multi-tier environments it scales far better than anything else. Additionally, you can (and should) separate the data-access layer from the presentation (UI) layer, which will later allow you to make changes to one subsystem (module, layer) without having to to change anything else.
Today, data can be anywhere and most of the times it is not stored on local computers or networks. Using DB-aware components to access that data can have significant negative impact on application and database performance. There are some data-access layers which improve this (UniDAC, AnyDac, ...), so using DB-aware components with them may get you better performance. Still, non-DB-aware components can outperform anything.
It is up to the developer to decide which mechanism to use, because, as I said, it all depends on what kind of application you are making and in what environment will it work.
This may be a carryover from experience with Visual Basic. As I recall, even Microsoft told developers not to use DB-aware controls in production code.
Delphi never had that problem, but as others have said, it depends upon the kind of project you are building and whether you run into performance issues.
Anecdote: a DB-aware control once messed up our InterBase database: to indicate a 'empty' or null date, the date edit control TcxDBDateEdit (ExpressQuantumGrid) uses a negative date value, which represents literally "01/00/0000".
So when users cleared the date edit field in the input form, and posted this value to the database, the records became unreadable (SELECT statements failed).
I have 50 or 60 records of four or five fields. I need to load the records into RAM (From a CSV file), search on different fields, enumerate, etc. Not a lot of data, not a lot of functionality.
I was all excited to use the new (to me in D2010) TDictionary or TList, but thought that a TClientDataset (which I've never used before) might be more appropriate.
With a TClientDataSet, I can use .Locate on any field, enumerate with while NOT CDS.EOF, etc.
And, what exactly is this MidasLib that I have to use with CDS? Can I reasonably expect it to be supported in the future?
Is TClientDataSet still considered state-of-the-art, or is it showing its age and somewhat deprecated (literally and figuratively)?
I've seen colleagues use DX's TdxMemData. Why use it (or any of the other handful of memory datasets I've seen while googling this issue) rather than a CDS?
Related question: Delphi: using TClientDataset as an in-memory dataset
TClientDataset is a very useful tool. You can do a lot of things with it that you can't do with a dictionary, such as filtering and binding data-aware controls. And it's still an active part of Embarcadero's toolset.
Midas is the in-memory database technology that TClientDataset is based on. It's a separate library, but there's a MidasLib unit that you can include in your EXE if you don't want an external DLL dependency.
As for TdxMemData, I've used it a little at work, but I don't care for it all that much. It doesn't have CloneCursor, which is one of TClientDataset's best features. It allows you to take a second client dataset and have it "clone" the first one, and then you have two client datasets that point to the same data store, but with different active records, filtering options, and various other properties. It's very useful for setting up multiple different "views" based on the same base data.
One of the projects I'm working on involves a module that needs to allow end users to create what essentially equates to, their own "object classes," storing data structures / record types that they can design and modify at runtime. The users will also be able to customize the user interface considerably, but that is not so much the scope of this question.
The closest example to what we are striving to build with this functionality, that I've seen, would be something very akin to what InstantObjects provides at design time, except our system would provide it at runtime, and put the class design control in the hands of the end-user (who will generally be pretty technically sophisticated, obviously).
I recently came across this list of Object Persistence Frameworks for Delphi Win32:
http://tdelphihobbyist.blogspot.com/2008/01/win32-object-persistence-frameworks.html
Any recommendations as to which of these might be the most conducive to the kind of runtime flexibility we are trying to create?
There is currently ongoing discussion of this in the tiopf newsgroups. Tiopf is a open source object persistence framework. Currently it doesn't support user modifiable objects but it looks like someone will be adding this functionality shortly.
Main site: http://tiopf.sourceforge.net/
News groups: See http://tiopf.sourceforge.net/Support.shtml
See "tiOPF ad runtime modifications" thread in the support newsgroup.
JSON could be used to declare and modify user-defined data structures at runtime. There are two libraries for Delphi, SuperObject and lkJSON. With JSON, object hierarchies would be easy to build. The SuperObject demo sources include examples for many usage areas.
SuperObject also contains iterator methods for a given JSON object structure.
I use it for a Delphi client library which is able to exchange objects with Java using the ApacheMQ message broker.
You can create some form of persistence using xml and then buil a form acordingly, we do this a lot for configurable filter windows for example
I have developed application for drawing some shapes (lines mostly) , now i need to be able to store sketch to a file, I know that delphi has build in routines for object persistence, but I have never used it.
Can someone tell me can object persistence be used if i have to persist object that have also references to other objects (that will be stored to), I have TLine object which can be connected to other TLine object etc.
Is it better to use this feature or write custom procedure to store/read object to/from file.
The built in object persistance is primarily designed for use in streaming components to a dfm, the work that you would need to do to persist your sketch would not benefit very much from that mechanism.
I think that you would be better off coming up with a custom scheme.
One method that I have used in the past is to store my object properties in an XML file writing a custom "save" routine which adds to a passed IXMLNode, and a new constructor which reads from a passed IXMLNode. I store component as a node, and the properties as attributes (unless the property is another object, then it would be a child node).
I believe there are some routines in the Delphi Jedi project which will handle component streaming for you, but I have not used them directly as most of my XML streaming has been done by hand since my objects were extremely simple and could be rendered with only a handful of properties.
I use the TI Object persistence framework (tiopf.com). I wrote the overview at http://tiopf.sourceforge.net/Doc/overview/index.shtml.
It will let you save objects and lists to xml, csv, databases etc. It handles child objects automatically.
If you are interested, use the svn version, not the sourceforge download as it has more features (inc partial D 2009 support).
You also can use the famous hibernate know from java.
the delphi port you can find here:
dHibernate
JSON is a new and very compact way to store objects. Two libraries are available for Delphi: SuperObject and lkJSON.
With NativeXML from http://www.simdesign.nl/xml.html I accomplished to read/write delphi in-memory objects from/to XML code. Very nice, very easy, with demo included here: http://www.simdesign.nl/forum/download/file.php?id=236