Adding a field to a cloned TClientDataset in DELPHI - delphi

Hi I have a master and cloned TClientData set
CdsCloned.CloneCursor(CdsMaster,true);
CdsMaster has two Fields 'SessionId' and ’UserID'
CdsCloned will have the same Fields
QUESTION: is it possible to add an extra field to CdsCloned without changing the CdsMaster ?

There are really two questions here: Can I add an extra TField, and can I add an extra data field.
When you clone a client dataset cursor, you end up with two TDataSet instances, each with their own collection of TFields, which share a single data store. You can certainly add additional TFields for things like calculated fields to one or the other without affecting the clone. There is no problem with doing this.
But remember, the original dataset and its clone share a single data store. You cannot change that data store without affecting the other dataset. If you add a new field to the data store, then that new data will be present in the store referenced by the original dataset, whether or not you have created any TField objects to read/write it. If this is starting to sound like a bad idea, well, that's what I'm thinking, too.
Finally, if you want the original dataset and its "clone" to have different data stores, then you can assign the Data property instead of using CloneCursor. When you do this, the data from the original is copied into the data store for the "clone", but the original and "clone" no longer share a single data store.

Related

Core Data: Which record loads by default in core data if you do not specify which one?

I have a static table for settings where I want to pull some stuff from an entity in Core Data. The use case does not lend itself to a table of records as you usually see. Rather each row of the static table is really a field related to the user--as in a user profile. I have a feeling that in testing I may have created more than one record in the entity. I know there are programs that let you see the SQL lite database underneath, but my question assumes you do not have this tool and are relying just on Xcode.
My question is when you have more than one record in a Core Data entity/table, and you try to load data from the managed object context into a VC, one field into one element, what record is shown by default?
Related to this, if you don't know how many managed object or rows are in the database, is there anyway to specify which record you want since there are no auto ids as you would use in a traditional database?
The record that gets loaded from the fetch first. Depending on your sort that might be consistent or it might be random.

How can a user add a new field to a table by creating a new attribute

I'm new to Core Data and I got stuck at this part of my xCode project.
I have created a core data entity "Person" and this entity has the following attributes:
name;
age;
birthday;
address;
and this attributes are getting displayed in a tableview. So far so good.
My problem is that I want the table to have an "Add Field" or "Add Row" cell so when the user wants to add more information in addition to these already created attributes he just clicks the cell and chooses the field name and type.
For example if he wants the person's "phone number" in the detail view of the table he names the new field "phone number" and chooses its type "number". Then he has an extra field where he can add the person's phone number.
How can I do this in core data? Is there a way for a user to manually add a new attribute to an entity and choosing its format? What is the best approach? Thanks.
You can't do exactly what you want with Core Data. Core Data can't change structure except if you make a new version of your design, but you do that in xcode.
But you can easily add another table called f.ex. information, which links to the person single connection and has the person linking back many to the information table.
This way, you can add as many fields and values as you want, of course all the extra fields you add would follow the same person, so if you want to use cellPhone field, you must add that to all.
I would recommend that you use direct SQL, and don't use Core Data. Core Data is not a database, it is an object store, and when you get better at iOS development, you will understand the difference, it is much bigger than you might think at first.
There is an excellent high level library for SQLite, called FMDB, you can find it on github here : https://github.com/ccgus/fmdb
Here you can do direct SQL queries like "Alter Table" and more on the fly, though what you are after isn't very simple, it could be real fun project to do.
Good luck with this.
I don't think this is directly possible in Core Data because its purpose is object persistence and you can't add new properties to objects dynamically. It could be faked to some degree using a to-many relationship to an "extra property" entity that had name, value (as string), and data type fields.
I believe your best option would be using SQLite in order to modify the table structure on the fly. (http://www.sqlite.org/lang_altertable.html)
My last company did something like this, but its not trivial. I don't have access to the code so this is more or less going to be from memory.
you provide transformable property in your entity (which will be a dictionary)
the model object has to provide the getter and setter for this that in turn drive the primitive methods to set/get an attribute
you provide a getter/setter along the lines of -objectForKey and -setObject forKey, which read and write values
when you are told to 'fault', you update the dictionary in the entity
In summary, maintain a dictionary of key value pairs. Perhaps you maintain a shadow dictionary that gets initialized and updated as needed. Its been around 4 years since I last saw this code so a little fuzzy on it. But you should get the idea. It was like magic - you can arbitrarily set any key/value pair (assuming string keys and NSCoding compliant values), and can always ask for the keys by asking the dictionary for its current set of keys.

Using a ClientDataSet in Delphi, are you able to display both Data & Delta records in a DBGrid?

I am making a app in Delphi 6 + MySQL database using standard data-aware components and dbExpress. The app allows a users to view records in a grid and edit data (insert and/or delete records) client side. These data edits are then only written to database on clicking the submit button. All of this works fine and has the following setup:
Controls:
1. DBGrid1 linked to a DataSource1 to display data visually.
2. DataSource1 is linked to ClientDataSet1 to offer data for DBGrid to display.
3. ClientDataSet1 is linked to DataSetProvider1 to provide client-side data for editing.
4. DataSetProvider1 is linked SQLDataSet1 which selects records from a single DB table.
5. SQLDataSet1 is linked to SQLConnection to provide connection to MySQL database.
Actions:
1. User inserts a record: I use ClientDataSet1.InsertRecord;
2. User deletes a record: I use ClientDataSet.Delete;
3. User submits data: I use ClientDataSet1.ApplyUpdates(-1);
This all works great in terms of handling data & posting data (with the inclusions of a small hack on DataSetProvider1BeforeUpdateRecord to delete records).
NOW FOR MY PROBLEM:
When the user first loads the form, the DBGrid1 displays all original records, removes all deleted records. But when the user inserts a new record in ClientDataSet1, a blank record is displayed in DBGrid1. The actual data is not lost or set as NULLS as when you ClientDataSet1.ApplyUpdates, this record is correctly written to the DB.
I know TClientDataSet has a data property for original data and a Delta property for edited data. Can these two properties with data by displayed in a single DBGrid at one time & still allowing the user to edit the data?
I have looked at 30+ resources and demo apps & all avoid this issue. Can this be done?
Ok...this question has been viewed a fair amount without much feedback. I did some research by downloading many tutorials, demo apps & read multiple articles/help info discussing the use of these controls.
The net result:
These controls are a bit buggy in general.
In specific reference to my question, it is safe to say the controls cannot do what I describe as a standard.
This is based on the 30+ demo apps, articles and tutorials I reviewed that either don't describe displaying both the original data with Delta data in a single data grid. Sure you could hack this outcome (which is what I did) using a Listbox or StringGrid, but that also indicates the control cannot or not usable at providing this functionality (on the slim chance it might).
This functionality is an obvious oversight in my opinion as a user wants to see the potential outcome of their actions, conveniently in a single data grid AND a developer wants to provide that in a simple & pain free way i.e. using a datagrid to display data!
Question Answered [if you can prove differently with a demo app that I want to review, I will remove this].
If you created a demo app and couldn't get it to work, up vote my answer. Thanks
The TDBGrid control provided with Delphi does not have the built-in functionality to display both the old and new values for fields. You are welcome, of course, to inherit from the Grid or create your own and add the functionality, or buy a third party component that accomplishes what you want. You are not limited to the standard controls, though they do provide the most commonly required functions.
You can also accomplish what you want by using calculated fields. For example, if you have a String field Name, add a new calculated String field to the dataset called OldName, with the same length as Name.
Then in your OnCalcFields event for the dataset, simply enter code like the following:
if DataSet.State = dsEdit then
begin
DataSet.FieldByName('OldName').Value := DataSet.FieldByName('Name').OldValue;
end
else
begin
DataSet.FieldByName('OldName').Value := Null;
end;
TClientDataset will handle itself the correct record status. Changes are logged, but unless you ask it explicity to show some other status (see StatusFilter property), it will show the actual state of a record.
It is possible InsertRecord bypasses some notification mechanism, so the field display is not updated. What if you perform simpy an Insert and the set field values?

Master-Detail with jqGrid+Asp.Net MVC and transaction

I'm coming from the delphi world and I want to make a master/detail interface, like Order and Products.
I already made actions to display the data using fields and a jqGrid. What I want know is how make possible to add lines, edit or remove them, but, just make the changes in db when the user confirm the changes in the master.
On delphi I would use a TClientDataSet with all the in memory changes and just after the confirmation would execute them inside a transaction like:
BEGIN
Master.Post
FOREACH Line IN Lines Line.Post
COMMIT
So in resume, I don't know how keep in memory the array of lines in the grid and how send them back to server to commit.
Any help will be appreciated. Thanks in Advance.
You'll need to keep track of the changes client side, perhaps using some hidden fields and/or form fields in your grid. When a line is deleted (that previously existed in the db), you'll need to add it's id to a field containing lines to delete. Lines that are added need to have associated form fields containing their data. When the master is committed you roll the whole set of fields up into a POST and send that back to the server.
Using LINQ to SQL, you'd create a data context, get the master object, then delete the related objects (from the hidden field of ids) that are so marked and create/add new related objects that didn't exist before taking the values from the appropriate form fields. Then you'd do a SubmitChanges and all of the statements would be executed within a single transaction.

Create a New big Object Wizard: ASp.net MVC

Here's my question:
I need to write a wizard, for customers to "create a new" very big objetc, with some other asociated with it: for example, Some images stored in another table (with relationships), some Lat's and Lang's for google earth, etc.
Each of them are stored in diferent tables in the Database, and that's why, i have to first insert to get the first object's Database generated ID to make the relationships with the another Objects. That's the reason I think puttin' Everything on just one View and hide selective DIVs with Jquery is not one of my option.
Session isn't an option because of the bigger object.
And because of the type of website, the wizard MUST be as follows:
Basic details of objetct 1
Images of object 1 (I will need here the ID of the first object)
Geolocations (with google maps, as before)
More details of object 1.
Preview
Publish
The point is, in step 4, user fill some fields that are required by the DB, and I cannot make them nullable as is it part of the customers reqs.
If somebody can a least give Ideas, will be nice...
Thanks in advance
You state that storing your object in Session is not desirable because of the size of the object. An alternative is to serialize that object and store it in the database. As the user progresses through the wizard, that object gets retrieved, updated and stored back in as a blob. Once they publish it, you can insert the appropriate records and remove the serialized object from whatever table you're storing them in.

Resources