AutoID Field in Many-to-Many, Insert Using TDataSet / Query (Delphi / MSAccess) - delphi

I have a database of "Items", which are assigned to multiple "Categories". Categories can have multiple items, and vice versa. The relevant portion of the database structure is as follows:
[tblItem]
ItemID (AutoNumber)
MainText (Text)
[tblCategory]
CategoryID (AutoNumber)
Name (Text)
[tblItemCategory]
ItemID (Long Integer)
CategoryID (Long Integer)
I want to build a panel component which shows a category name at the top, with a databound grid of items belonging to that grid below. There will be many instances of this panel component, and the end-user should be able to create a new item and simultaneously assign it to the category in question from any one of them.
In MS Access, it's possible to create a nested form, with the "child" one databound to a query which is "MasterFields" linked to a databound "Category" field on the "parent" form, such that the grid of items changes as the Category field is changed. This Items grid can also easily have new records added to it, with both the ItemID (in tblItem AND table tblItemCategory) and the linked CategoryID field (in tblItemCategory) being populated automatically.
The query for that Access form's grid is:
SELECT tblItemCategory.CategoryID, tblItem.*
FROM tblItemCategory LEFT JOIN tblItem ON tblItemCategory.ItemID = tblItem.ItemID
ORDER BY tblItemCategory.CategoryID;
If I try the same thing in Delphi, the ItemID AutoNumber field doesn't get populated, resulting in the following error:
..exception class EOleException with message 'The field 'tblItemCategory.ItemID' cannot contain a Null value because the Required property for this field is set to True. Enter a value in this field'.
..and the ItemID field is accordingly blank in the grid.
Is there a way to get Delphi/ADO to handle the behind-the-scenes two-table ItemID population as easily/neatly as Access does, without manually handling it programmatically? If not, what's the best/most elegant way to handle it programmatically?
I'd like to keep whatever solution I end up with as closely tied to the conventional TDataSet / TDataSource approach as possible, as I use a number of different kinds of databound controls, all of which will have to deal with this same data structure.
(Note: I'm using Delphi 2007 and an MSAccess 2000 format MDB file.)

Pretty much the same way. Theres's master source and master fields properties, so you just chain detail to master.
So mastersource would be Customer, Detail Source, Orders linked by CustomerID.
Dead easy to show this, but hard to explain.
Some other bloke wrote it all out though.
Master Detail Forms And Delphi

If you want to add new records to the tables via the grid, then you will have to use the BeforePost method of the underlying query in order to obtain the new key, which you then insert manually into the link table along with the category id.
I admit that I never write code with editable (and insertable) grids so my answer may need a little tweaking.

Related

Vaadin: How to remove item from DB container grid

How do I remove a row from a container/item/grid/db/entity/bean/class/object/ID?
Also, what's the difference between all these?
Everyone seems to say these as if they were interchangeable.
Can I get a simple explanation of how these all work together?
I've been through dozens of youtube videos and tutorials, but I still can't see the big picture.
Simple task: Delete one row from a grid.
But then it starts getting bigger and more complex with nested beanitem container property field entities and I just can't make sense of it.
Thank you for all of your help in advance!
The Grid, Table or any other Vaadin Component used to present set of data use some implementation of the Container to store your data. A Component is a part of your User Interface, the <div> in your DOM which is seen by your end user. The Vaadin Containers contains your objects. The most widely used containers are:
IndexedContainer - default container for Grid and Table. You usually add items by calling addItem method on either container or related component. The disadvantage of using this type of container is that you are usually obligated to set appropriate properties (think of columns) on both items and the container itself,
BeanContainer - is able to receive Java objects that follows JavaBean convention. Thus it is able to automatically infer properties of your component,
SQLContainer - contains data stored in database. Constructed using SQL query. Can be setup to automatically update your database based on changes made by user in UI.
Items and IDs
Adding single items to some containers may look a bit complicated. There are a few ways to do this. They are described very well on a Vaadin website. Basically the ID is an unique object that you use to access corresponding Item. The Item is represents the single row in your component. Every Item have properties. You can access and make changes to your items in container using their IDs i.e.
table.getItem("uniqueId");
Usually, you don't operate directly on containers. The components expose basic Container interface methods via their API. In example implementation of AbstractSelect.getItem() component currently (Vaadin 7.5.9):
protected Container items;
public Item getItem(Object itemId) {
return items.getItem(itemId);
}
(AbstractSelect is a super class of other Vaadin components like Table and Grid)
It gets more complicated with properties of the items. Every Item have some properties (columns). And every Property has its corresponding ID. Using property ID you can access the value of the item in the specific column. The following code presents above - it adds one item with one property and sets its value:
Table table = new Table();
table.addContainerProperty("column1", String.class, "defaultValue");
Item item = table.addItem("uniqueId");
item.getItemProperty("column1").setValue("Black Friday");
Notice that it is perfectly safe to use String literals as IDs since underneath they are compared using equals()

Is there a ComboBox that has Items like a TcxRadioGroup?

The TcxRadioGroup component of DevExpress has a very nice way to specify items. You can specify a Caption and a Value (and a Tag) for each TcxRadioGroupItem.
The TcxComboBox and the normal TComboBox of Delphi on the other hand use TStrings to store its items.
While TStrings can have a Name and an Object, there is no easy way to hook up a name and a value using the form designer of the Delphi IDE.
Is there a ComboBox control (preferably from DevExpress) that allows to visually design its items with a Caption and a Value?
PS: I'm not looking for a DB aware control.
Try a TcxImageComboBox. See here - you don't have to assign images despite the name. You can also edit the items visually.
(I use it as cell editor in cxGrids because of the separation Description/Value.)
Raize Components have TRzComboBox which introduces a Values property as an addition to the existing Items.
ESBPCS for VCL has an enhanced Lookup ComboBox. It stores 2 Lists, the ones normally in TCombobox's Items as well as the new Values list. These two StringLists are in a 1-1 relationship. Use AsItem to retrieve the string currently displayed and AsValue to retrieve the "related" string from Values.
Use a standard Delphi TComboBox, it can store a string (for visualization, and an object of any TObject descendant that you implement yourself, i.e you can store anything associated to a string in the dropdown).

Delphi: What is the quickest way to populate a dropdown box via a qry result?

Ok, so I have a database query, that returns the countryname column
SELECT CountryName FROM Counties
How would I put all these country names into the dropdown boxes Items option (without looping through them?)
I'd use something like the TDBLookupComboBox. Drop one on the form and set the properties like this.
DataSource = srcCustomers
DataField = 'country_id'
ListSource = srcCountries
ListField = 'NAME'
KeyField = 'ID'
This code will display the country name on the form and place the country id in the db Customers.country_id.
The two controls that start with src are TDataSources connected to TADODataSets. You can connect the datasources to many different data access controls.
My Delphi is a little rusty but you should have something along the line of ->
comboBox.Items //A list so you can just add to it.
you can then take your result, loop over it and deal with the issue like any other Windows framework. Look up the TADOQuery (or whatever you're using) to get the results. Delphi is pretty straightforward, inspect the object and you'll probably see a solution materialize.
Use something like that:
ComboBox.Items.Assign(CountryList);
Where CountryList is a TStringList instance containing all country names.
This is the fastest way of populating a TComboBox.

Add calculated column with checkboxes to datagrid

In my application I have a TcxGrid (devexpress datagrid) that displays the data returned from a stored procedure.
Now I would like to add a column showing checkboxes from which the values cannot come from the database but are calculated internally.
When the checkboxes are clicked, some internal logic needs to be triggered.
Any suggestions?
#boris, I recommend you use the Support Center site of DevExpress for this type of question, there are thousands of articles to DevExpress products.
Anyway I leave here a link to something that might help ;)
How to set up an unbound item in a data-aware View
Are you creating the view at runtime or at designtime?
I sort of cheated when I did this at runtime, and returned a static value as one column from my query:
select false as processed,col1,col2 from table where true
I could then safely attach the dataset, and I had my new column to play with.
You would then perhaps use the properties.onChange or properties.onEditValueChanged for your logic code.

Showing many tables in many dropdown lists. c#, asp.net-mvc, linq2sql

I want to use an example to explain what I want.
Assume I've following DB design:
Item (id, name, categoryID);
Category (id, name);
When user wants to create an Item (fill in form), I'll give a list of categories in a dropdownlist, and when user chooses one of the categories ASP.NET MVC will automatically bind categoryID, to the selected one. I need to present same dropdown list when editing the item with correct selected one.
Question:
But my DB is very big, and it requires around 30-40 (maybe even more) category-like tables, that contain just "id" and "name", and all tables need to be shown in dropdown list while creating some other object, and also needs to be presented while editing the object. Definitely above schema doesn't work, because it's tedious to write same logic 100 times with just different table names. (I'm using Linq2SQL)
Currently my solution is:
Make a view that's based in all such tables and in application I just call a function that construction dropdownlist from that single view. But it's still tedious to change view definition everytime I add a new table.
Do you guys think of a better solution for this tedious work, possibly using reflection or some other tecnologies.
It is not a problem "Definitely above schema doesn't work, because it's tedious to write same logic 100 times with just different table names."
If I were you, I will mark an addition interface on these class using "partial class" feature.
Then, I will write few extension method for the partial class.
If anyone interested in the solution:
I've used reflection to solve this problem.
I use reflection over DataContext to get the Table (by string name), and get its fields and construct the optionlist.

Resources