Monday, November 7, 2016

A Special Year for Delphi Developer Days

Delphi Developer Days 2016 with Nick Hodges and me, Cary Jensen, is just around the corner (we start in Chicago a week from today). And, the Delphi Developer Days book has been printed, which for an author is that one milestone that is always rewarding. As in years past, this book is once again weighing in at about 400 pages.

This year is very special for another reason. We started planning Delphi Developer Days 2016 back in late May, and this year I have the pleasure of working with my longtime friend and former Delphi Product Manager Nick Hodges.

Nick has been a prolific writer over the past couple of years, publishing not one, but two Delphi books (Coding in Delphi and More Coding in Delphi). I was really looking forward to working with him on the Delphi Developer Days book, and I was not let down one bit. This book is loaded with good stuff, and I cannot wait for our chance to present this material.

But that is not the special part I am talking about. My past Delphi Developer Days presenters have all been serious contributors to the Delphi community. Marco Cantù has gone on to become the current Delphi Product Manager. Bob Swart continues to speak at conferences, publish articles, and runs the Delphi Developer Network in the Netherlands (and I look forward to his return to Delphi Developer Days as my co-presenter next year). Ray Konopka continues his great work, and both Konopka Signature Components and Code Site are bundled with various versions of Delphi. And then, in September, we learned that Nick had joined Embarcadero as the Director of Product Management, and will be overseeing Delphi as well as other Embarcadero products.

But even with that great responsibility, Nick is committed to completing this autumn's Delphi Developer Days tour. And what a special gift for our attendees. Not only are they going to hear one of the really gifted Delphi presenters, but they will be interacting with one of the people Embarcadero has entrusted with shepherding Delphi, and other products, into the future.

There are still some seats available for our Chicago and Baltimore events, and Frankfurt is almost full (Copenhagen has been sold out for over a month now). So, if you want to be a part of one of the coolest Delphi events this year, you have got to act soon. Oh, yeah, and you get your own copy of this year's Delphi Developer Days 2016 book. (Sorry, this book is available only to Delphi Developer Days attendees.)


Tuesday, October 11, 2016

When Migrating to FireDAC, You Must Understand UpdateMode

Let's start with a little history lesson. When Delphi first shipped it had one data access framework, the Borland Database Engine (BDE). While the BDE was a breakthrough product in its early years, providing a fast, independent, and easy-to-use data access layer, it was cumbersome to install, used a lot of network bandwidth, and had limited support for remote database servers. Over time, it became increasingly obsolete.

The need for a new data access mechanism for Delphi became even more apparent during the development of Kylix, a Delphi-based compiler and IDE (integrated development environment) for Linux. Porting the BDE to Linux was ruled out, and dbExpress was born. The dbExpress data access framework is high-speed and client/server friendly, largely based on pass-through SQL (structured query language).

The dbExpress framework has one major drawback, however. In most cases converting a BDE project to dbExpress required a major refactoring of the data access logic, and dbExpress did not support the old-style file server databases, such as Paradox, dBase, or MS Access until Delphi XE2. As a result, for most many developers dbExpress was a poor option.

FireDAC changes that. Conversion from the BDE to FireDAC is pretty smooth, and Delphi even ships with a tool, named reFind, that helps with much of the conversion process. It is for this reason that I use FireDAC in all of my new projects (and all of the database projects included in my source code for Delphi Developer Days). In addition, I think that a good argument can be made for migrating legacy applications to use FireDAC when a major revision is scheduled. Yes, it is that good.

One Big Difference: UpdateOptions.UpdateMode

One reason why migration to FireDAC from the BDE is so easy is that FireDAC provides a solid implementation of the TDataSet Interface, and all of the basic operations available in the BDE can be found in FireDAC. Better still, FireDAC implements many of the higher-end features previously only found in ClientDataSets. As a result, if you know the BDE and/or ClientDataSets, using FireDAC is a no brainer.

There is one very significant difference between how FireDAC and the BDE/ClientDataSets work, and this difference is very easy to miss, in part because it is related to the default value of a single property. And because the effects of this property have such a profound impact on how your database applications work, it is important that you know about this difference when you decide to start using FireDAC. The property is UpdateMode.

UpdateMode is a property found in the UpdateOptions property of FireDAC TDataSets. It is also a property of BDE TDataSets as well as the TDataSetProvider when used to apply updates to a caching ClientDataSet. In all of these mentioned classes the UpdateMode property performs the same task, it influences how the corresponding component generates the SQL used to write changes to the underlying database.

The UpdateMode property is of the type TUpdateMode. The following is the declaration of the TUpdateMode type:

TUpdateMode = (upWhereAll, upWhereChanged, upWhereKeyOnly);

Here is how it works. When UpdateMode is set to upWhereAll, all non-BLOB fields are included in the WHERE clause of UPDATE and DELETE queries. This results in update failures if any of the non-BLOB fields of the underlying record were modified since the time that the table was opened, the query or stored procedure was executed, or the FDMemTable was loaded. This approach is known as optimistic locking, and when two or more users are trying to apply changes at about the same time to the same record, only the first to apply changes will succeed. All others will fail.

When UpdateMode is set to upWhereChanged, only the primary field keys and the fields that have been modified are included in the WHERE clause of UPDATE queries. (Again, INSERTs are not affected. DELETE queries continue to use an exact match criteria since there are no changed fields in a deleted record.) As long as none of the primary key fields of an updated record are affected, and all non-primary key fields that have been modified have also not been updated in the underlying table since the time the data was loaded into the DataSet, these queries should succeed.

Using upWhereChanged permits two or more users to apply their changes to the underlying database so long as none of them have made changes to common fields. For example, if one user changed a field called Address, and another changed a field called PhoneNumber, and neither of these fields are part of the primary key, both users will successfully apply their changes. This type of update permits merges.

The final UpdateMode value is upWhereKeyOnly. With UpdateMode set to upWhereKeyOnly, the WHERE clause of UPDATE queries only includes the values of the primary key fields. (INSERT and DELETE queries continue to act as they do with upWhereChanged.) Using this mode, so long as the key fields of the underlying record have not been changed, the updates are applied, replacing any updates that other users may have applied.

Assuming that key fields are not touched (this is a pretty safe assumption in most database architectures), the use of upWhereKeyOnly permits everyone to succeed in posting their changes. As a result, the last user to post is the user whose data appears in the underlying database.

The Difference and Why It Is Important

The default value of FireDAC's UpdateOptions.UpdateMode is upWhereKeyOnly, and this is a really big deal. It means that if you use FireDAC datasets without changing this default value, there is a good chance that some users may report that their changes have disappeared. Or, even worse, never know that their edits have been overwritten.

Here is how this can happen. If two or more users read the same record (by way of a query, stored procedure call, or by opening an FDTable), and two or more post a change to that record, the last user to post their record will replace those changes posted before them. What's problematic about this is that the users who posted before the last user will have no idea that their changes have been overwritten.

By comparison, most developers prefer to use either pessimistic locking (the first user to start editing the record prevents any other user from editing the record until changes have been posted), or optimistic locking (once the first user posts a change to a record, subsequent attempts to post to that same record will fail, since the original record no longer can be found, based on the WHERE clause predicates). In these scenarios, the first user to post wins, and other users must first re-read the record, after which they can decide whether or not to update the newly posted contents.

FireDAC defaults to an UpdateMode of upWhereKeyOnly, since the queries required to update the database tend to execute faster. It is up to you, however, to decide whether or not the performance improvement is more important that the possible loss of data.

The DataSetProvider class, the class which ClientDataSets use to resolve changes back to the underlying database, and BDE DataSets (TTable, TQuery, and TStoredProc) also have an UpdateMode property. For these objects, the default value of UpdateMode is upWhereAll, the conservative setting that prevents a user from overwriting another user's edits.

So, the bottom line is this. You need to understand how FireDAC's UpdateOptions.UpdateMode affects how records are updated in the underlying database, and set this property to the value that meets the needs of your application.

An Easy Solution, If You Want to Change UpdateMode

Fortunately, another feature of FireDAC makes it easy to change the default value of UpdateOptions.UpdateMode property. The UpdateOptions property, like a number of other properties in FireDAC, is found in a number of classes in the FireDAC framework, including FDManager, FDConnection, FDQuery, FDMemTable, and so on.

These classes are related in a hierarchical sense, in that the settings found in the UpdateOptions property of the FDManager (a singleton object) are inherited by all FDConnections configured to use the FDManager. Similarly, any FireDAC dataset, such as an FDQuery or FDMemTable, will employ the settings found in the FDConnection to which they are connected.

So, if your application is using one FDConnection, changing the UpdateOptions.UpdateMode property of that FDConnection will automatically apply that setting to any FDTable, FDQuery, FDStoredProc using that connection (so long as you have not already touched the UpdateOptions.UpdateMode property on any of these TDataSets). If you are using more than one FDConnection, add an FDManager and change the value of the UpdateOptions.UpdateMode property there, and that change will likewise cascade down to any FDConnections, and then on down to the individual TDataSets, again, so long as that property has not also been overridden in any of the individual FDConnections or TDataSets.

Note that if your FDQuery, FDStoredProc, or FDTable is already connected to an FDConnection, and that FDConnection currently uses upWhereKeyOnly, changing the FDConnection UpdateOptions.UpdateMode property alone might not change the FireDAC DataSet. You might have to disconnected, and then re-connect the DataSet to the FDConnection before the DataSet's UpdateMode property updates.

Copyright © 2016 Cary Jensen. All Right Reserved

Tuesday, July 12, 2016

Delphi Developer Days 2016 with Nick Hodges and Cary Jensen Agenda Published

The agenda and course topics for this year's Delphi Developer Days with Nick Hodges and me, Cary Jensen, has been released, and we think that you will be pleased with the selection of topics. Over the course of this two-day event we will have a combination of talks, some of which are jointly presented by Nick and me, as well as talks where we break out into separate rooms to cover a variety of topics.

For our joint sessions we are covering threading and thread synchronization, the parallel programming library, code de-coupling, dependency injection, and a debugging deep dive. We are also going to discuss best practices in professional development, a thought-provoking look at the principles and philosophies crucial to success in the art of software development. And finally, no Delphi Developer Days tour would be complete without the Tip, Tricks, and Techniques session, were Nick and I share some of our favorite tricks-of-the-trade.

I am really excited about presenting these joint sessions with Nick. Over the past couple of years Nick and I have co-presented talks at several Delphi conferences, and each time it was not only fun for us, but also provided our audiences with a deeper understanding of the subject matter. Nick and I are passionate about the topics we picked for our joint sessions, and the opportunity to present them jointly gives us the chance to really explore the issues, and provide a contrast of opinions and solutions.

Topics for our separate talks including unit testing, FireDAC, advanced Delphi language features, patterns in Delphi, building Windows services, and using JSON (JavaScript Object Notation). As in the past, these joint sessions are concurrent, meaning that you'll have to choose between two simultaneous topics. But you'll miss nothing, as Nick and I are publishing the material for each session in the Delphi Developer Days course book. This course book, which in the past has been well over three hundred pages long, is only available to attendees of Delphi Developer Days.

Along the way we'll also have a keynote address from Embarcadero, question and answer sessions, and the opportunity to network with fellow Delphi developers. For a detailed agenda and descriptions of each of the topics, please visit http://www.DelphiDeveloperDays.com/descriptions.html.

We are very fortunate to have Nick join us for Delphi Developer Days this year. Over the past several years Nick has published two books on Delphi, Coding in Delphi and More Coding in Delphi. He is getting ready to publish his next book, Dependency Injection in Delphi, and you don't want to miss this chance to hear one of the leading Delphi experts share his views and insights. I hope to see you at Delphi Developer Days 2016 in Chicago, Copenhagen, Frankfurt, or Baltimore.

Register by August 12, 2016 and save 25% off of the regular price. For more information, and to register, visit http://www.DelphiDeveloperDays.com

Tuesday, June 7, 2016

Delphi Developer Days 2016 with Nick Hodges and Cary Jensen

It is my great pleasure to announce that Nick Hodges will be joining me for this year's Delphi Developer Days tour, which will visit the United States, Europe, and Scandinavia late this autumn. Delphi Developer Days are intense, two-day training events focusing on Delphi, the cross-platform, rapid application development platform from Embarcadero Technologies.

The tour will begin in Chicago on November 14th and 15th, and will continue in Copenhagen, Denmark on November 24th and 25th. We will be in Frankfurt, Germany on November 28th and 29th, and will conclude the tour in the Baltimore/Washington DC area on December 5th and 6th.

Delphi Developer Days consists of both joint talks, where Nick and I present a topic together, as well as individual sessions where we focus on various aspects of Delphi development. As we have done in the past, each attendee will receive a printed book containing the material from all of our talks. In the past these books have been in excess of 350 pages long, and this year looks to be no different.

I am especially proud to have Nick Hodges presenting with me this year. Nick is one of the original members of the Delphi community, and the author of arguably the first custom Delphi component (TSmiley). He is the recipient of the coveted Spirit of Delphi award, one of Embarcadero's Delphi MVPs, and a regular presenter at Delphi conferences and web casts. Nick previously served as the Delphi Product Manager, and has recently published two celebrated books on Delphi (Coding in Delphi, and More Coding in Delphi).

Nick is both an excellent presenter and writer, two talents that are essential for Delphi Developer Days. He is the perfect addition to the list of co-presenters that I've had the honor to work with over the years. My Delphi Developer Days co-presenters in previous years were Marco Cantú (currently the RAD Studio Product Manager), Bob (Dr.Bob) Swart, and Ray Konopka (Raize Software). Bob is still involved with Delphi Developer Days, but is unable to commit to travel this fall. I look forward to his return to Delphi Developer Days in 2017, but in the meantime, I am delighted to have Nick stepping in as a first-rate replacement.

Nick and I are currently working on our agenda, and we will announce our topics in the next couple of weeks. Registration is now open at www.DelphiDeveloperDays.com, and if you register in the next several weeks (prior to August 12, 2016), you will receive a 25% discount on the registration fee. We've sold out many of our events in the past, and with Nick on board for this tour, I anticipate that seats will go fast.

Just a final note. Normally Delphi Developer Days tours occur in the spring. We had to postpone our spring tour this year due to the unexpected loss of a close family member. Thank you to all who supported us during this difficult time, and thank you also for your patience. We are very happy that we are able to provide a 2016 tour, and with the addition of Nick, it's guaranteed to be one of the best Delphi Developer Days tours yet.

Sunday, January 24, 2016

Delphi Developer Days Postponed

The annual spring Delphi seminar known as Delphi Developer Days has been postponed due to circumstances beyond our control.

Loy Anderson (the DDD event manager), Bob (Dr.Bob) Swart, and I have been working to put together this year's Delphi Developer Days, and we were getting close to announcing our dates when Loy and I suffered the tragic and sudden loss of a close family member. The circumstances of this event are going to require that Loy and I spend a significant amount of time helping out our family. Unfortunately, it is not possible to provide this help and at the same time invest the time required to make Delphi Developer Days a success.

We will make an announcement once we have re-scheduled the Delphi Developer Days dates. If you would like to be informed once new dates have been chosen, you can visit www.DelphiDeveloperDays.com and click the link labeled Notify Me. I will also blog and tweet once we know when the next DDD event will be offered, as well as post this information to the official Delphi Developer Days site and the Delphi Developer Days Facebook page (https://www.facebook.com/delphideveloperdays).

Thank you for your understanding, and we look forward to seeing you at the next Delphi Developer Days...

Cary

Friday, February 13, 2015

Using Trim in ClientDataSet Filters

I announced in my last blog post that an updated version of Delphi in Depth: ClientDataSets is now available, both in printed and in eBook formats. In response, a reader posted this question as a comment:

I used TClientDataSet.Filter. CDS's Filter support "Trim" statement in Delphi help doc. It support "Trim(Name, '.')". But, how to used the statement?

Here is the answer. Imagine that your ClientDataSet includes a Company field, and that you have set the ClientDataSet's Filtered property to True, and have entered a Trim statement in the Filter property.

When you call Trim you can pass either one or two parameters. If you pass one parameter, you pass the name of a field. In response, Trim will remove any leading and trailing white spaces (please see the first comment below). For example, the filter Trim(Company) = 'Unisco' will trim white space, and the filtered data will include records whose Company field includes 'Unisco ', '    Unisco', '  Unisco  ', and 'Unisco'.

If you include the second, optional parameter, Trim will return the value of that field after removing that leading and/or trailing character. As a result, Trim(Company, 'o') = 'Unisc' will match on 'Unisco', 'oUnisc', and 'oUnisco. Likewise, Trim(Company, '.') = 'Unisco' will match on 'Unisco', '.Unisco', 'Unisco....', and '...Unisco.'.

There are two variations on Trim. These are TrimLeft and TrimRight. Like Trim, these functions can also take one or two parameters. If you call TrimLeft or TrimRight with only one parameter, those functions will remove white space from the beginning or the ending of the specified field, respectively. If you pass a second parameter, TrimLeft or TrimRight will remove that character from the beginning or ending of the specified field, respectively.

For example, TrimLeft(Company, 'U') = 'nisco' will match on a record whose Company field contains 'Unisco' and 'nisco'. Likewise, TrimRight(Company, 'o') = 'Unisc' will match on a record whose company field contains 'Unisc', 'Unisco', and even 'Uniscooo'.



Monday, January 12, 2015

Now Available: Delphi in Depth: ClientDataSets 2nd Edition

I published the original Delphi in Depth: ClientDataSets book back in March of 2011. At the time I believe it was my 24th book on computer software, though I must admit that I've lost count. Nonetheless, I greatly appreciated the many kind comments I've received from readers since its publication, even though it is a Delphi book "about one component."

I decided to update the code samples following the release of Delphi XE7. My original code samples made use of the Borland Database Engine and the sample Paradox tables that shipped with Delphi, which permitted those code samples to be compiled and run without any additional configuration, something that I felt was important.

Things changed with the release of Delphi XE7. The BDE is no longer installed by default. In addition, Delphi Professional (and higher) now ships with an alternative database solution that can be used without any additional configuration. This solution, which makes use of FireDAC and InterBase, did not exist when the first edition of this book was published.

Once I started updating the code samples to use FireDAC and InterBase, I realized that there were also a few additions that I could make to the original book. For example, the new FieldOptions property introduced to TDataSet in Delphi XE6 gave developers additional flexibility in their use of persistent fields, such as calculated and internal calc fields. A nod to LiveBindings would also be warranted.

It didn't take long before I concluded that it was time to give the book a good once over, tweaking the odd description here and there, adding material where appropriate, and correcting a few missed typos. And, of course, using the new FireDAC/InterBase examples in the book's code listings. I also updated all of the figures in the book to show the latest version of Delphi at the time of my writing (XE7). The original BDE/Paradox examples are still available for download, which is necessary in order to support older versions of Delphi, those prior to XE5. XE5 was the first version of FireDAC to use the new FD prefix in component names, as well as the new FireDAC unit names.

Permit me now to anticipate a question that is sure to come up. "What if I bought the original edition of Delphi in Depth: ClientDataSets? Should I buy the 2nd edition?" Well, you probably don't need to buy the 2nd edition unless you want to have the most current version on your bookshelf. In updating the 2nd edition I re-read, for the purpose of correcting and editing, every page of the original manuscript many times. And, for the most part, I was very happy with what I had written. As a result, there are large segments from the original text that are unchanged, or have inconsequential changes in the wording. Yes, I did add sections on FieldOptions, LiveBindings, and special filter operations. There are also a few additional examples and extended discussions.

I should also note that you can use the new FireDAC/InterBase samples with the original book. Visit the book's download site, listed in Appendix A of the original publication. There you will find the FireDAC/InterBase code sample download, along side the BDE/Paradox code download. Again, these FireDAC examples only work with Delphi XE5 and later, so the BDE-based examples are still available for use with earlier versions of Delphi.

I should also note that I removed three chapters that appeared at the end of the original book from the 2nd edition. Those chapters covered DataSnap, with a mix of COM-based DataSnap and the newer DataSnap introduced in Delphi 2009. While ClientDataSets played a central role in the COM-based DataSnap (the obsolete version), they are one of many options in the new DataSnap. In the end, I concluded that the DataSnap chapters were out of place.

I am releasing two versions of Delphi in Depth: ClientDataSets 2nd Edition. The printed version is available on CreateSpace and Amazon. And, in response to popular request, I am releasing a PDF version on FastSpring. You can find links to these releases from the book's web site at http://www.JensenDataSystems/cdsbook2.

I am very happy with how Delphi in Depth: ClientDataSets 2nd Edition turned out. I hope that you are too.

Publication Date: Jan 07 2015
ISBN/EAN13: 150584018X / 9781505840186
Page Count: 358 pages, 7.44" x 9.69"

Web Site: http://www.JensenDataSystems/cdsbook2