Scenario
This example illustrates how to connect your application to another database after the application is already started. This can be required for a multi-tenant application where you need to associate a user or company with their own database of the same structure. You can choose a required database and user during the login procedure and also later in the application UI by using the specialized SingleChoiceAction (available for Admin only). The created databases will have the same structure, but can have a different predefined data set.
Steps to implement
1. Using the XAF Solution Wizard, create a new XAF app named RuntimeDbChooser and that uses XPO for data access and the Security module with the Authentication = Standard and UI-level mode options.
2. Copy code that creates predefined security users for each database from the RuntimeDbChooser.Module\DatabaseUpdate\Updater.xx file into YourSolutionName.Module/DatabaseUpdate/Updater.xx;
3. Copy and include the RuntimeDbChooser.Module\BusinessObjects\CustomLogonParameters.xx file into the YourSolutionName.Module/BusinessObjects folder;
4. Copy and include the RuntimeDbChooser.Module.Web\WebChangeDatabaseController.xx and RuntimeDbChooser.Module.Web\WebCustomAuthentication.xx files into the YourSolutionName.Module.Web project;
5. Copy and include the RuntimeDbChooser.Module.Win\WinChangeDatabaseController.xx and RuntimeDbChooser.Module.Win\WinCustomAuthentication.xx files into the YourSolutionName.Module.Win project;
6. Copy and include the RuntimeDbChooser.Wxx\WxxApplicationEx.xx files into the YourSolutionName.Wxx project;
7. Replace the line that instantiates your WinApplication descendant in the YourSolutionName.Win/Program.xx file with the CreateApplication method call as shown in the RuntimeDbChooser.Win/Program.xx file.
8. In the Application Designer invoked for the YourSolutionName.Web/WebApplication.xx file, select the Authentication Standard component and set its LogonParametersType property to RuntimeDbChooser.Module.BusinessObjects.CustomLogonParametersForStandardAuthentication
You can learn more on the approaches used in points 2-4 from the eXpressApp Framework > Task-Based Help > How to: Use Custom Logon Parameters and Authentication article.
Question Comments
Added By: Mario Blatarić at: 11/5/2012 11:23:09 AM
Let me give you "some reasons" why this isn't such a specific scenario.
- accountant company doing accounting for several different companies (it's business requirement that data for each company is in separate database)
- building maintenance company - again - business requirements demands each building to live in separate database (because of financial data)
- document managment companies doing document management for multiple companies - again, each company must live in seperate database
- local community combined with utility company - same people do both things and want to keep things separated
If you like, I can go on. No, you can't go to this companies / communities and say "But, it's better if we put all this to one database" because they will reply "Thank you, we'll find someone who can do it with multiple databases".
The point is, there are many reason why one piece of software should be connecting to multiple databases, so it's not such a specific scenario really. It would be nice to have this functionality out of the box instead of implementing this hard to understand piece of code.
Also, since application is distributed to many different clients, it would be nice that end-user could setup application on first startup (add/create required databases with connection info).
This example doesn't work.
Go to WinChangeDatabaseController.cs and set breakpoint in changeDatabaseAction_Execute. This code never executes since created SingleChoiceAction is not visible on logon form, instead some default editor is created with PredefinedValues and it's behaviour is not modified.
Can you fix this code please?
@Mario: I have answered you in www.devexpress.com/issue=Q484359
This example worked correctly in my tests. In any event, I have just updated it to .NET Framework 4.0, just for more convenience.
Thanks Dennis. I understand now how this works.
Added By: lekan odejimi at: 1/29/2014 1:28:06 AMHi Dennis, each time i try to logon i keep on getting this error: "Make sure your user name is correct and retype the password in the correct case." What do you suggest?
Added By: Grégoire Perruchoud at: 3/20/2014 9:52:00 AMHi,
Great piece of code !
I noticed a weakness. In Web/Win controllers, preselection of correct item is done via following code :
if (Application.ConnectionString.Contains((string)item.Data))
This fails in case database name's string is contains elsewhere in ConnectionString. It also fails in case we have multiple databases with names containing each other, for example "customers" and "customers_geneva".
We should store the current database name in a static property somewhere and make a strong comparison.
Added By: Achmad Mulyadi at: 8/15/2015 12:11:19 AMHi Dennis,
From the code below,
public const string Databases = "ChangeDatabase_DB1;ChangeDatabase_DB2";
Is there anyway I can pass a dynamic attribute value? I know this attribute requires a fixed value in compile time, but I don't think it is practical to put the database name or maybe a server address in a hard coded way. For example, it would be very practical if we can read this value from the app.config file, and pass it to the ModelDefault attribute.
Added By: Dennis (DevExpress Support) at: 8/17/2015 8:12:50 AM @Achmad: Sure, please check out a possible solution at How to make example E1344 work with runtime defined databases. I hope this meets your needs.Added By: Robert Sanford at: 12/21/2015 3:36:59 PMHi Dennis,
Would it be possible to post a complete XAF solution that incorporates this logic please along with tutorial? I have a single database XAF app that now has multiple database requirement - the various sql server databases would be defined in web.config. Thanks
@Robert: Thanks for your suggestion. We will take it into account for the future.
In the meantime, would you please submit a separate ticket and describe your business requirements in greater detail? It is possible that you can use other approaches to meet them. For instance, I feel that How to connect different ORM data models to several databases within a single application can be suitable here.
Dennis, yes I will do that, thanks. Basically, I need to take an existing XAF VB.NET solution - one model, one database - and expand this to several databases, allow user to authenticate to their database based on user/account ID. Each SQL server (SQL Azure database) will be identical. Thanks
Added By: Dennis (DevExpress Support) at: 12/23/2015 1:04:34 AM @Robert: Thanks, I will answer your new Convert existing XAF solution to allow access multiple idential databases authenticated by UserID ticket.