Is it possible to sort a TDBGrid on a lookup field? - delphi

I have a DBGrid with a column based on a lookup field.
How can I set it up so that when a user clicks on the column title, it will sort by that field.
My problem here is that I can't figure out a way to create an index on a lookup field.
I'm using Absolute Database for this, but most things that work with the BDE or TClientDataSet will work with Absolute.
Thanks!

I don't think it is possible to create an index on a lookup field. It is possible to create an index on an internally calculated field of a ClientDataSet though. In the OnCalcFields event handler set its value to the value of the lookup field. And set the visible property of the lookup field to false. Now you can sort on the internally calculated field.

What you could do (especially if the data is readonly, and does not have zillions of rows) is use a ClientDataSet to display data in your grid.
Roughly the steps would be like this:
Load the data from your regular into the ClientDataSet,
add a calculated field to the ClientDataSet that contains the value obtained from the lookup,
then add an index to that calculated
field.
--jeroen

You cannot sort by a lookup field. But you can 'fake' this. Let's suppose that you have the following tables: (PK means Primary Key)
Contacts
ID - Integer (PK)
NAME - Varchar(40)
COUNTRYID - Integer
Countries
ID - Integer (PK)
NAME - Varchar(40)
Then you can have the following query in the dataset which is linked to the TDBGrid:
SELECT C.ID, C.NAME, C.COUNTRYID, CO.NAME
FROM CONTACTS C
JOIN COUNTRIES CO ON C.COUNTRYID=CO.ID
(Not tested but I think that you got the idea)
Also you can put this in a view.
Then you'll display in your TDBGrid (as columns) only the ID, NAME and the desired lookup field which you already have (let's call it COUNTRYLOOK).
When one clicks on the Title Header you can change the query by adding in the 4th line an ORDER BY . For the specific column of the lookup field (COUNTRYLOOK), instead of using the 1:1 mapping you can put in the 4th line of your query ORDER BY CO.NAME. Reopen the query and that's it. In practice is much more simpler than my description here.

DevExpress ExpressQuantumGrid can do it, check it out:
http://www.devexpress.com/products/vcl/exquantumgrid/

Related

Loop over all model fields in Rails/MongoDB

I am using mongoid/Rails for my application server. I defined my own field typ 'formula'. This is a field I don't want to have persistent in the database since this is not a data field but a formula which is consistent across all records of a model. So I stored this formula in my metadata and whenever I create dynamically a model where I need this formula I create a field with my custom type 'formula' where the formula is the default value. This works so far - but as soon as I save a record which includes my formula field it doesn't.
So before I create or update any records I want to loop over all fields of my model and depending on the type the field I allow it to be updated - or not ( so for every formla field I don't allow updates)
I can loop over all field names (model.fields.keys.each) and check the name of the field - But I haven't found a method to loop over all fields and access the type. Any idea?
But perhaps there is another way to avoid my formula field is saved in the database? I create a mongoize (object) method for my new field type 'formula' and this method simply returns nil - but this still writes an empty field to the database.

Delphi 7 updating joined tables

I'm working with Delphi 7 and Firebird database. I'm using TIBDatabase, TIBTransaction, TIBQuery, TIBDataSet and DBGrid to establish connection and provide user interface for working with table. In my database I have two tables:
Ships
fields
Id integer
Name varchar(20)
Type_Id(Fk) integer
Longth integer
Ship_types
fields
Id(Pk) integer
Ship_type varchar(10)
So resulting dataset which I get through "join" query has such fields
Name
Type
Longth
Type is Ship_type field from Ship_types table joined via query by Type_Id foreign key to this table from Ships table.
Data is displaying properly.
Then I need to edit my data directly through DBGrid. For this purpose I use TIBUpdateSQL component. For displaying Type(lookup) field I chose DBGrid.Columns.PickList property.
So my question is how can I make TIBUpdateSQL work with such type of field? Cause I know that if it would be single table without foreign keys I have to write update statement into ModifySQL property of update component. But what have I do with fk fields? Can I write update join statement in UpdateSQL component or, if not, what else way I can do it?
I don't need to update two tables, I just need to update only Ships table but there is varchar(word representation) field in displaying dataset and in updating dataset it must be integer(corresponding id) to suit to table structure.
Editor in TIBUpdateSQL isn't solution for me cause I'm assigning query to TIBQuery on runtime.
You can't update tables using select with JOIN, only with subselects.
Sub-select example:
SELECT TABLE_NAME.*
, (SELECT TABLE_NAME2.NAME FROM TABLE_NAME2 WHERE TABLE_NAME2.ID = TABLE_NAME.ID)
FROM TABLE_NAME

How to get IQueryable.ToList() with database fieldnames instead of entity properties

The scenario:
I have a considerable amount of entities as models in CodeFirst mapped to the database fieldname with the Attribute [Column("str")].
I have a bunch of Reporting Service Reports (in local-mode) with the DataSets mapped to the database field names.
I can't pass direct results of linq queries to those reports with the ToList() method because of the field names. What I can do (and I'm trying to avoid) is to type select new for each object; or run each query via a different datasource.
Question:
I would like to know if there is any trick to have a IQueryable object with the original field names instead of the property names. Something like a dynamic select new.
Any suggestions will be appreciated.
No, there isn't. The database column names either have to match the property name, or you have to use the Column attribute to make them line up. That's your only choices.

Excluding column from insert

Is there a way to map a column in Code First, so that it is populated on select, but not used when inserting or updating?
If I apply the [NotMapped] annotation, the property/column is not populated, but if I do not add this annotation, when inserting, it complains that the column does not exist.
Reason I ask, is that I have a query, that performs a join and returns a value for the column, but on insertion, this column is not needed.
any idea's?
Cheers
Edit:
Just an update to explain in a little more detail what I am doing.
Previously, I had two tables,
Carer
CarerID
UserID
IsPrimary
User
UserID
But then, it was requested that a Carer can belong to more than one User, so I had to create a link table, as below.
UserCarer
UserCarerID
UserID
CarerID
IsPrimary
What I didn't want to do is, is how I've temporarily resolved this, is to create a method within my entity that then initializes another context to get the value.
Instead, I was hoping that when I selected the data, I would perform a left join to get the IsPrimary value from the UserCarer table thus allowing me to keep any reference to Carer.IsPrimary
i.e. select * from Carer.*, UserCarer.IsPrimary from Carer left join UserCarer on Carer.CarerID = UserCarer.CarerID where UserCarer.UserID = #p0
HTH
That is only possible if you mark the column as computed or identity (autogenerated at insert) but it has another consequences - EF will try to select that column after update or insert so if it doesn't exist in your table you will still get an error.
It looks like you are trying to populate class which is not entity and such class cannot be used for persistence! If you have custom join in the query it means that you are doing projection / view of data and the result is most probably not entity = should not be used for saving changes.

Cleanest way of filling a disabled input field via DB

I have created a form which allows the user to add to an inventory of items, stored in a database. Each item in the Inventory table is associated with a UID which is auto-incrementing, non-editable, and effectively auto-generated.
The top field in the form is ItemID, which has input disabled and is merely there to inform the user of the ID of the new item they are about to add.
Ideally, here's the pseudo-code:
<input type="text" name="email" value="<% (SELECT Max(ItemID) FROM dbo.Inventory).ToInt32 + 1 %>" disabled="disabled"/>
I already have a Linq to SQL ORM set up. This is all being done in MVC, so the idea occurred to me to figure out the correct value inside the form's controller and then just passing it to the view directly.
What would be the cleanest, simplest way to achieve this? I think ideally, the "value" field should be no more than 1 line.
This approach won't work.
If ItemID is auto-incrementing field what components increase its value? Anywhere but the database you will run into trouble. Assuming you do use a database assigned field, when you populate your input field with a value you take the next available value at that time. What happens though if two forms are read and submitted out of order? The Id you populate in your value field will not match up with id the database will assign. So this only would potentially work for a single user at a time.
Best is to let the DB assign the value when you do the actual DB insertion using an identity column and not worry about doing this manually or even trying to predict the id - don't populate the value field this way.

Resources