i'm developing a custom component, and i'd like to add a published property that would be an array of TQuery (it should be visible in the object inspector). the main feature would be to drop the component on a form and then visually select the queries that are present on the same form, or on any other project form.
is that doable? from what i've seen till now, you can only programatically use such an array property...
UPDATE
first, thanks for your answer Alex!
second, the chatch is that i have to modify an old app someone else created, so i want to tangle with it as little as possible (actually there's a second app i need to "fix" which i was told is twice as big). now for the details: the app has abou 15 forms for various db operations. as you can imagine each form has 2-3 TQuery objects. the problem is that the user must authenticate with the db in order to execute the queries, thus he knows the db user & pwd which is a security flow.
in order to avoid this, an intermediate system has been introduced. one connects & authenticates with it and requests the necessary db data: user, pwd, and database name. my job is to use this system and autologin to the db. the necessary credentials to access this intermediate system are not considered a security flow so i'll read them from an inifile that depends on the environment where it's deployed: test, pre-production, production.
so i placed a TDatabase component on my form, setting its LoginPrompt property to FALSE. the tricky part however is adjusting each TQuery to the diferent database name for each environment before execution..
dunno if i made myself clear but it's the simplest explaination i managed to come up with
thanks,
G
To make life as simple as possible, you may have to grin and bear it once:
Create a datamodule and make sure it gets instantiated before the main form.
Put your TDatabase component on that data module.
Go through all your forms once and
add the database's data module to its uses clause (can be in implementation section).
Change all your TQuery and other database related components once to use the database component from the data module instead of having their own connection strings.
At run time, login as you described via your TDatabase component et voila, all your components will now use these settings automagically (as they are all connected to your TDatabase instance).
Okay, you've added a TDatabase to your project. Now, fill the "DatabaseName" property of TDatabase with some random name. Every TQuery component in your project also has a "DatabaseName" property and fill in the same name in those properties! Now your database and all it's queries will be connected and you could use the TDatabase object to access them all.
Yes, it can be done but you will have to write your own Property editor with it's own input form to manage the data inside the array. There's plenty of information to be found online. And yes, you could create a component that checks for controls on it's parent, allowing you to access those.
But is it practical? Why do you need an array of TQuery components in design time? Maybe you need to rethink your design first, so you're absolutely sure that you need this functionality. (Besides, what's wrong with using a Data Module to contain your queries?)
Related
I am making a user form in Delphi for documents tracking application. I am interested in functionalities input new entry (record) and view list by... (date, name of document, ID,...).
My problem is that I don't know how to implement these functionalities for more than one user. Currently, I have 5 users. Each user has a unique input data (record) fields (columns) and view fields (columns) of each user are also unique. There could be more users.
So, how to implement these functionalities for this form? How to assign different data (fields) for each separate user for input and view? That is what I don't understand. Is that distributed functionality of an application? If yes, how to achieve it?
Note that I don't want static assigning of a user in application's code, e.g:
if(username='user1') then {
input();
view();
}
else if (username='user2') then {...}
...
because, than, every time there is a new user, developer must go back to the application's code and hard-code it. That is not efficient and is a bad implementation. Rather, I want that to be dynamic (if that is the right term). How to achieve this?
Note: I am using dbExpress tool with MySQL DBMS with RAD Studio XE7 Architect.
If I'm correctly understanding what you are asking, it seems as if you are unfamiliar with the idea of tables/datasets which operate in a so-called Master-Detail relationship. These are very easy to set up in Delphi.
Once you get familar with M->D relationships, I think you'll realise that what you should have been asking about is how to set one up in your app, rather than the problem of hard-coding of individual users into your form.
In your case, what you are missing at the moment is a table of users' details. Let's call that the Users table. Usually this would contain their name, obviously, and some kind of unique identifier (best is a "Primary key" in the Users database table), but NOT, please, their password to access the db, especially not in plain text.
Once your Users table is created, you can create a display grid (TDBGrid) and input/editing form for it.
Then, if you don't have it already, you could set up a grid and editing form for users' documents (which I'm going to refer to as the Documents table).
Once that's done, the main thing left to do is to set up in your Delphi project a Master-Detail relationship between your Users table (the master) and your Documents table (the detail).
If you prefer you can have a single form with two grids, the Users grid and the Documents grid on it, and as you scroll through the Users grid, you'll see that the Documents grid shows only their document records.
The details of how to set up a Master-Detail vary somewhat according to the type of table/dataset you're using so you'll need to search online for the details of how to do it. Broadly, it's a matter of connecting a TDataSource to your Users table and setting the DataSource (or MasterSource) property of your Documents table to point at the Users TDataSource, and then setting a couple of other, table-type-dependent properties of the Documents table.
Every edition of Delphi since well before D7 has come with a demo app, "MastApp" which illustrates how you use Master-Detail relationship amongst a number of tables. I suggest you take a look at the MastApp for your Delphi version and then look into how to set up M->D relationships for the type of Delphi dataset you are actually using.
I have a connector that selects data from an external database in Bonitasoft, I was able to assign the result of this select to a process variable and display the contents of that variable in the UI Designer in an Input type field, however I need to display this in a table, as I configure This in the UI Designer to display the contents of my process variable in a table, if possible show the step by step thank you. Another thing as I can also pass the contents of my connector to a business variable and then display in UI Designer also if needed
First of all I want to draw your attention that using business or process variables to store data already stored in an external database will lead to duplication.
Recommended solution would be to use a REST API extension (such as REST API SQL data source) to query the data from the external database and use this REST API extension in the forms.
Now if you are ok with duplication of data you can refer to an example I create that demonstrate how to set process and business data with PostgreSQL connector output and then display the variables in form table widgets.
I highly recommend to use business variable and if possible consider migrating the data from the external database to the business data database.
I have a bit of problem here. I have created a lookupfield in my application server using Delphi XE2 DataSnap technology. On the client side, that field becomes TStringField. Now, the problem is that I loose the lookup functionality on the client side. To top that, I can't change the stringfield on the client side because it is read only (even if I manually turn off the read only property).
I don't want to lookup tables on the client side because I don't want all the data loaded on my client side just to support look up.
I can change the Key field value, but the stringfield lookup text doesnt change unless I apply updates and reload the data.
Users want to see the text change.
What should I do?
Seems you have to review your GUI functionality: lookup fields are really an client side feature. And it needs the lookup source - so to use it on client the lookup table must be loaded. DataSnap guys are very nice here, converting it to an TStringField when transmitting it to the client... I would simply ignore it.
So, if the lookup table is that big, you shouldn't using lookup fields but search UIs - or autocomplete comboboxes which you do queries against the DataSnap Server. Maybe you have to code it manually in the combobox case, I don't know (see if JVCL have something you can use to shortcut the path).
Alternatively, if the lookup table are seldom updated, you can aggresively cache it and have an updating mechanism to detect changes. So you can use the lookup fields the way they were created for.
Long time ago i faced that problem and i found a solution that is a bit complex to analyze here but i try to give some guidelines till i have the time to write a detailed blog post.
The idea consists of info (concerning lookup fields such as field properties, datasets, providers) packaged by the provider as optionalparams at the server side.
At client side a derived TClientDataset can unpack and process these info, create on the fly client datasets that retrieve needed lookup datasets and setup it's lookup fields accordingly.
The process is transparent due to the embedded functionality in the derived client dataset class and the only things to remember is to create that info in the provider's OnGetDatasetProperties event and turn false all provider flags in lookup fields.
In my program I have multiple databases. One is fixed and cannot be changed, but there are also some others, the so called user databases.
I thought now I have to start for every database one connection and to connect to each data dictionary. How is it possible to connect to more than one database with one connection by handing over the data dictionary filename? Btw. I am using a local server.
thank you very much,
André
P.S.: Okay I might find the answer to my problem.
The Key word is CreateDDLink. The procedure is connecting to another data dictionary, but before a master dictionary has to be set.
Links may be what you are looking for as you indicated in the question. You can use the API or SQL to create a permanent link alias, or you can dynamically create links on the fly.
I would recomend reviewing this specific help file page: Using Tables from Multiple Data Dictionaries
for a permanent alias (using SQL) look at sp_createlink. You can either create the link to authenticate the current user or set up the link to authenticate as a specific user. Then use the link name in your SQL statements.
select * from linkname.tablename
Or dynamically you can use the following which will authenticate the current user:
select * from "..\dir\otherdd.add".table1
However, links are only available to SQL. If you want to use the table directly (i.e. via a TAdsTable component) you will need to create views. See KB 080519-2034. The KB mentions you can't post updates if the SQL statement for the view results in a static cursor, but you can get around that by creating triggers on the view.
I have an application that has different data sets depending on which company the user has currently selected (dropdown box on sidebar currently used to set a session variable).
My client has expressed a desire to have the ability to work on multiple different data sets from a single browser simultaneously. Hence, sessions no longer cut it.
Googling seems to imply get or post data along with every request is the way, which was my first guess. Is there a better/easier/rails way to achieve this?
You have a few options here, but as you point out, the session system won't work for you since it is global across all instances of the same browser.
The standard approach is to add something to the URL that identifies the context in which to execute. This could be as simple as a prefix like /companyx/users instead of /users where you're fetching the company slug and using that as a scope. Generally you do this by having a controller base class that does this work for you, then inherit from that for all other controllers that will be affected the same way.
Another approach is to move the company identifying component from the URL to the host name. This is common amongst software-as-a-service providers because it makes sharding your application much easier. Instead of myapp.com/companyx/users you'd have companyx.myapp.com/users. This has the advantage of preserving the existing URL structure, and when you have large amounts of data, you can partition your app by customer into different databases without a lot of headache.
The answer you found with tagging all the URLs using a GET token or a POST field is not going to work very well. For one, it's messy, and secondly, a site with every link being a POST is very annoying to work with as it makes navigating with the back-button or forcing a reload troublesome. The reason it has seen use is because out of the box PHP and ASP do not have support routes, so people have had to make do.
You can create a temporary database table, or use a key-value database and store all data you need in it. The uniq key can be used as a window id. Furthermore, you have to add this window id to each link. So you can receive the corresponding data for each browser tab out of the database and store it in the session, object,...
If you have an object, lets say #data, you can store it in the database using Marshal.dump and get it back with Marshal.load.