This is somewhat of an age-old debate, but I'm wondering if there's anything new about using WEB Core to build an app with separate forms that let you edit DB fields?
If you're using a DBMS with a REST API, like StellarDS, in most ways this looks like a VCL app using SQL Server or MySQL on the LAN. Delphi's TDataSets and DB-aware controls hide most of the complexities, but the forms are separate things. So I'm curious if anything changes depending on where the DB Connection and/or the DataSet controls are located -- in a DM, the Main form, or the form doing the updates? I've seen them all used.
But also, I'm wondering if there's any reason to favor one of these options or the other:
-
Connection on main form or DM, select a record, send the DATA to a form for viewing and/or editing using normal controls, then get it back and update the DB if it was changed; versus,
-
Select the current record that you want to use, then open the form to view and/or edit the record, and have it interact with the DB itself using DB-aware controls.
If you don't have uniform access rights for everybody, does this impact one of these approaches over the other?
(I've worked on Delphi apps that use both methods in existing code, but I've never really built one from scratch nor had to dive into all of the issues. My apps have mainly used simpler data stores, like INI files -- which aren't very compatible with web apps (since they can't be stored locally) unless you have a way to host them behind an API.)
We have modeled the use of DataModules in a TMS WEB Core application similar as how you would use DataModules in a VCL application.
I've seen all of these variations used. I'm asking if there are any reasons to prefer one approach over others.
Both approaches have their pros and cons, and the choice depends on maintainability, security, and how user access rights are managed. Let's break down the considerations:
Approach 1: Connection on Main Form or DataModule
- Workflow:
- A record is selected.
- Data is retrieved and passed manually to another form (non-DB-aware controls).
- The form allows users to edit the data.
- On save, changes are sent back and applied to the database.
Pros:
More Control Over Data Handling
- You explicitly manage when and how data is written back, reducing unintended updates.
- Allows business logic validation before updating the DB.
Security & Access Control
- Since editing occurs in a detached dataset (e.g., using local variables or objects), users without write access can view data without modifying it.
- You can validate user permissions before sending updates to the database.
Better Concurrency Handling
- Prevents locking records unnecessarily (since changes happen locally and are only written back when the user confirms).
Easier to Work with APIs or Multiple DBs
- This model is similar to handling REST APIs or multi-database architectures, making it more flexible.
Cons:
More Code & Complexity
- Requires additional code for transferring data between forms.
- Need to manually track changes and update the record accordingly.
Can Be Less Responsive
- If the dataset is large, pulling all the necessary data first before opening the form can slow down performance.
Approach 2: DB-Aware Controls & Direct Interaction with the DB
- Workflow:
- A record is selected.
- A form opens with DB-aware controls (e.g.,
TDBEdit
, TDBGrid
), which are directly connected to the dataset.
- Any changes are instantly reflected in the dataset.
- The form can commit or cancel updates directly.
Pros:
Faster Development & Simpler Code
- Less code is needed because DB-aware controls automatically reflect and update data.
Live Data Editing
- No need to manually pass data between forms; changes are instantly applied.
Ideal for Small to Medium Applications
- If users are always expected to have write permissions and concurrency issues are minimal, this method is straightforward.
Cons:
Potential Security Issues
- If a user has edit access, they can modify data without additional validation, unless explicitly checked before saving.
- Access control must be enforced at the dataset or DB level.
Concurrency & Locking Issues
- If multiple users edit the same record, who wins?
- DB-aware controls might keep a record "locked" while editing, leading to blocking issues.
Harder to Manage Access Restrictions
- If different users have different permissions, you need additional logic to disable controls dynamically.
Access Rights & Choosing the Right Approach
If users have different access rights, Approach 1 is the better choice:
- It allows granular control over who can edit data.
- Read-only users can view data without affecting the database.
- Write access can be validated before committing changes.
If all users have uniform access rights, Approach 2 is faster and easier to implement.
Which One to Choose?
Criteria |
Approach 1 (Manual Transfer) |
Approach 2 (DB-Aware Controls) |
Security & Access Control |
Better for role-based permissions |
Harder to manage |
Concurrency Handling |
Safer, avoids unnecessary locks |
May cause record locking |
Performance |
Slightly slower (manual data handling) |
Faster (direct DB updates) |
Complexity |
More code required |
Simpler, automatic DB binding |
Scalability |
Works well with APIs, multi-DB |
Limited to direct DB access |
User Experience |
More predictable (controlled saves) |
Risky if the user accidentally modifies data |
Final Recommendation
- If you need strict control over access rights and concurrency, go with Approach 1 (Manual Transfer).
- If you want rapid development and simplicity, Approach 2 (DB-Aware Controls) is fine for small-scale apps with uniform user access.
2 Likes
Wow, Bruno, this is a great synopsis of the issues. Thanks! This should be posted somewhere more accessible. It's the kind of detail that usually comes with lots of experience, and I've seen situations where these guidelines were not followed and they resulted in overly-complex code.
But a more common case that I've observed a lot is a combination where the DB info is passed to the form, either explicitly or implicitly; the form issues a query to get the data (if needed); user edits the form; then the data is saved back to the db (or added if new) before the form exits.
There are lots of ways to slice-and-dice this, but it looks like it mainly boils down to Security & Access Control needs, which is not something I've ever really considered. Usually it's approached from either "copy the data in and out of the form yourself" or "let the DB handle the data movements".
I've seen situations where every form had a TClientDataSet on it that was there only to support DB-aware controls on the form to reduce the need to move data around.
(Did you use ChatGPT to get this? It's unusually well-formatted.)