How do I connect Crystal reports to multiple database? - c#

I have a webpage which has a drop-down. In the drop-down there is a list of databases from a server. On selecting the drop-down document numbers are shown and we can click and generate crystal report.
My problem is I have given data-source for one database in the crystal report. Suppose I select other databases. How can I connect to the report for multiple databases?
Any inputs will be greatly appreciated.

Are you using CR designer or Visual Studio to make your reports? Because there is a connection section in the field explorer window. Generally, it is not recommend to connect to multiple DB. Even if you are using for example 2 or more stored procedures for your report, you can complicate your life if they don't have a common key.

The below is what we use, it should work for you. Basically you have to make sure that for every table the report accesses (or command, or view, etc.), the connection is set. I'm not aware of a way to set it only on the main report.
// create a ReportDocument
using (ReportDocument reportDoc = new ReportDocument())
{
reportDoc.Load(path); // path to your .rpt file
// get the connection string you want to use
SqlConnectionStringBuilder conInfo = new SqlConnectionStringBuilder("<your connection string>");
Tables crTables = reportDoc.Database.Tables;
int tablecounter = 0;
foreach (CrystalDecisions.CrystalReports.Engine.Table crTable in crTables)
{
CrystalDecisions.Shared.TableLogOnInfo logonInfo = crTable.LogOnInfo;
logonInfo.ConnectionInfo = new ConnectionInfo()
{
DatabaseName = conInfo.InitialCatalog,
ServerName = conInfo.DataSource
};
if (conInfo.IntegratedSecurity)
{
logonInfo.ConnectionInfo.IntegratedSecurity = true;
}
else
{
logonInfo.ConnectionInfo.UserID = conInfo.UserID;
logonInfo.ConnectionInfo.Password = conInfo.Password;
}
crTable.ApplyLogOnInfo(logonInfo);
}
}

Related

Changing the database location drops owner schema

We have hundreds of Reports created in 8.0.1.0 (I know they are old).
We created a Visual Studio 2010 C# application to run these reports. It's a Windows App. Had some trouble with the Web App.
The reports are all saved under the PROD environment.
We are working in a TEST environment.
We are using an Oracle environment and all the reports use the Oracle Server connection.
When we run the reports through C# we go ahead and change all the database locations to our TEST environment. When this happens the "Owner" (schema) information is dropped. The report fails with a 942 error.
Now if we don't change the database, keep it as PROD, everything works perfectly. It seems that by changing the database the schema information is dropped.
Any ideas. I've been searching around and can't find a solution.
Snippet of code:
connectionInfo.DatabaseName = "";
connectionInfo.ServerName = <SERVER>;
connectionInfo.UserID = <USER>;
connectionInfo.Password = <PWORD>;
foreach (Table crTable in crTables)
{
crTableLogOnInfo = crTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = connectionInfo;
crTable.ApplyLogOnInfo(crTableLogOnInfo);
// if you wish to change the schema name as well, you will need to set Location property as follows:
//crTable.Location = "<SCHEMA>." + crTable.Name;
}
I've tried to set the crTable.Location but the program locks up. So not sure what to do.
In the past we successfully changed connection parameters by doing this:
CrystalDecisions.Shared.TableLogOnInfo info = document.Database.Tables[iTable].LogOnInfo.Clone() as CrystalDecisions.Shared.TableLogOnInfo;
info.ConnectionInfo.ServerName = <SERVER>;
info.ConnectionInfo.DatabaseName = "";
info.ConnectionInfo.UserID = <USER>;
info.ConnectionInfo.Password = <PASSWORD>;
document.Database.Tables[iTable].ApplyLogOnInfo(info);
where document is CrystalDecisions.CrystalReports.Engine.ReportDocument.
Fixed it by doing this:
connectionInfo.DatabaseName = "";
connectionInfo.ServerName = <SERVER>;
connectionInfo.UserID = <USER>;
connectionInfo.Password = <PWORD>;
foreach (Table crTable in crTables)
{
crTableLogOnInfo = crTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = connectionInfo;
crTable.ApplyLogOnInfo(crTableLogOnInfo);
// if you wish to change the schema name as well, you will need to set Location property as follows:
//crTable.Location = "<SCHEMA>." + crTable.Name;
crTable.Location = "<SCHEMA>." + crTable.LogOnInfo.TableName;
}
I was setting the Location incorrectly. Thanks for your help!

why crystal report is getting all records even with RecordSelectionFormula set?

I am using the following code for loading crystal reports.
ConnectionInfo crconnectioninfo = new ConnectionInfo();
ReportDocument cryrpt = new ReportDocument();
TableLogOnInfos crtablelogoninfos = new TableLogOnInfos();
TableLogOnInfo crtablelogoninfo = new TableLogOnInfo();
Tables CrTables;
crconnectioninfo.ServerName = "localhost";
crconnectioninfo.DatabaseName = "dbclients";
crconnectioninfo.UserID = "ssssssss";
crconnectioninfo.Password = "xxxxxxx";
cryrpt.Load(Application.StartupPath + "\\rpts\\" + dealerInfo.ResourceName);
CrTables = cryrpt.Database.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in CrTables)
{
crtablelogoninfo = CrTable.LogOnInfo;
crtablelogoninfo.ConnectionInfo = crconnectioninfo;
CrTable.ApplyLogOnInfo(crtablelogoninfo);
}
cryrpt.RecordSelectionFormula = getCustInfoRptSelection();
cryrpt.Refresh();
allReportViewer.ReportSource = cryrpt;
getCustInfoRptSelection() is getting a specific client
but the report shows all the clients at first time and when i close the report and open it again it shows the correct record.
so basicly i have to open the report twice to get the correct data though the getCustInfoRptSelection() results is not changing.
and in this case the RecordSelectionFormula =" {dealer.dealer_type_id}=2 and {dealer.DEALER_NAME} like 'Mark stall X'"
I had the exact same problem, and I found this answer on a SAP website that worked
Expand Form1.vb|cs to show Form1.Designer.vb|cs and double-click it to show its code
Find where the initial crystalReportViewer1 properties are set in the the InitializeComponent method
Comment out or delete the following two lines:
this.crystalReportViewer1.SelectionFormula = ""
this.crystalReportViewer1.ViewTimeSelectionFormula = ""
Apparently this was something that was added in one of their newer service packs, as this problem didn't start happening until after I upgraded the Crystal Reports framework for .Net
This one nailed it.
Locate your Windows Form that contains the CrystalReportViewer Control.
Normally, your Windows Form has Resx file and designer file
Example:
Open the Designer file:
Delete the 2 lines below:
This I think is a bug.
I am using VS2015 VB.NET.
It worked!

Crystal Reports not chaging the server programatically

I'm developing a local app with friends and we're using svn, but we have crystal reports, but it saves the last server used by one of my friends when doing the commit. I tried changing the server programatically using this piece of code, but it didn't work :S
*UPDATE: it seems that the .rpt keeps a history of the server names, and somehow doesn't seem to clear the list, so my friends computer "\sqlexpress" is still there, and I can't seem to clear it :S"
string nombre = WindowsIdentity.GetCurrent().Name.ToString().Split('\\')[1];
ReportDocument cryRpt = new ReportDocument();
TableLogOnInfos crtableLogoninfos = new TableLogOnInfos();
TableLogOnInfo crtableLogoninfo = new TableLogOnInfo();
ConnectionInfo crConnectionInfo = new ConnectionInfo();
Tables CrTables ;
//cryRpt.SetDatabaseLogon(string.Empty,string.Empty, nombre + "\\sqlexpress","trupp");
cryRpt.Load(FinalPath);
crConnectionInfo.ServerName = nombre + "\\sqlexpress";
crConnectionInfo.IntegratedSecurity = true;
crConnectionInfo.UserID = string.Empty;
crConnectionInfo.Password = string.Empty;
crConnectionInfo.DatabaseName = "trupp";
CrTables = cryRpt.Database.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in CrTables)
{
crtableLogoninfo = CrTable.LogOnInfo;
crtableLogoninfo.ConnectionInfo = crConnectionInfo;
CrTable.ApplyLogOnInfo(crtableLogoninfo);
}
crystalReportViewer1.ReportSource = cryRpt;
crystalReportViewer1.Refresh();
You need to make a call to clear the existing connections from the report before setting the new ones.
cryRpt.Load(FinalPath);
// After loading report clear all datasourceconnections
cryRpt.DataSourceConnections.Clear();
// Now you can set new datasourceconnections
crConnectionInfo.ServerName = nombre + "\\sqlexpress";
Sometimes Crystal Reports can be a pain so if for some reason the above doesn't work you can always just set the server name on the existing connection embedded in the report.
cryRpt.DataSourceConnections[0].SetConnection(nombre + "\\sqlexpress", "trupp", true);
It's a pain in the neck, eh?
If you and your friends are using the same make and model of database table server, you might try putting an entry in each developer machine hosts file to create a local hostname alias, or if your development data bases are all on your own machines, use localhost.
If you use ODBC, you can all create your own ODBC entries with the same name and use those.

database login prompt with crystal reports

I'm trying to display some report with some subreports inside it, but every it shows the report it throws some dialog box asking for database connection. I'm using this code:
private void frmReporte_Load(object sender, System.EventArgs e)
{
Clave = ConfigurationSettings.AppSettings["Password"].ToString();
NombreBD = ConfigurationSettings.AppSettings["CatalogBD"].ToString();
NombreServidor = ConfigurationSettings.AppSettings["Servidor"].ToString(); ;
UsuarioBD = ConfigurationSettings.AppSettings["UserID"].ToString();
this.crtReportes.ReportSource = this.prepareReport();
}
public void imprimirReporte()
{
ReportDocument rpt = new ReportDocument();
rpt.Load(mvarRutaReporte);
rpt.SetDataSource(clsReportes.dsReporte);
rpt.PrintToPrinter(1, false, 1, 1);
}
private ReportDocument prepareReport()
{
Sections crSections;
ReportDocument crReportDocument, crSubreportDocument;
SubreportObject crSubreportObject;
ReportObjects crReportObjects;
ConnectionInfo crConnectionInfo;
Database crDatabase;
Tables crTables;
TableLogOnInfo crTableLogOnInfo;
crReportDocument = new ReportDocument();
crReportDocument.Load(RutaReporte);
crReportDocument.SetDataSource(clsReportes.dsReporte.Tables[0]);
crDatabase = crReportDocument.Database;
crTables = crDatabase.Tables;
crConnectionInfo = new ConnectionInfo();
crConnectionInfo.ServerName = NombreServidor ;
crConnectionInfo.DatabaseName = NombreBD;
crConnectionInfo.UserID = UsuarioBD;
crConnectionInfo.Password = Clave;
foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables)
{
crTableLogOnInfo = aTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = crConnectionInfo;
aTable.ApplyLogOnInfo(crTableLogOnInfo);
}
// Para los reportes que poseen subreportes
// pongo el objeto seccion del la seccion actual del reporte
crSections = crReportDocument.ReportDefinition.Sections;
// busco en todas las secciones el objeto reporte
foreach (Section crSection in crSections)
{
crReportObjects = crSection.ReportObjects;
//busco en todos los reportes por subreportes
foreach (ReportObject crReportObject in crReportObjects)
{
if (crReportObject.Kind == ReportObjectKind.SubreportObject)
{
crSubreportObject = (SubreportObject)crReportObject;
//abro el subreporte y me logeo con los datos del reporte general
crSubreportDocument = crSubreportObject.OpenSubreport(crSubreportObject.SubreportName);
crDatabase = crSubreportDocument.Database;
crTables = crDatabase.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables)
{
crTableLogOnInfo = aTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = crConnectionInfo;
aTable.ApplyLogOnInfo(crTableLogOnInfo);
}
}
}
}
return crReportDocument;
}
I had a similar problem and it is solved now, so I'm adding this reply in case it might help someone else in my situation.
When setting the SQL Server login info for the report, make sure you include the service name. So, for example, make sure you're giving Crystal "myserver\myservice" instead of just "myserver".
My program is able to access data from SQL Server using just "myserver", but Crystal needs to be given "myserver\myservice".
In crystal you can specify whether to prompt for db login # the time of report generation in Crystal Management Console (CMC) # each report level. Login to CMC, open your report > Process > Database. At the bottom of the page you can specify "Prompt the user for database logon", "Use SSO context for database logon" or "Use same database logon as when report is run". Select the third option for using the credentials stored in the server.
You can just write
report.SetDatabaseLogon("username", "pwd", #"server", "database");
give the login information then the database logon box will not appear when you will run the code.
Some older Crystal Report files saved with prior versions of the SQL Native Client (e.g. Provider: SQLNCLI) will no longer be able to login if either the client or server disables the respective TLS protocol version. For example, if a report was saved with SQL Server 2005 (version 9.00.xx), then TLS 1.0 is needed. If this protocol is disabled, there's no intuitive error, simply a "Database logon failed" is seen programmatically. Client software including rendering in a web browser will be prompted to enter a password, even though the account may have proper SQL permissions.
If rendering reports in IIS applications, see a tool called IISCrypto from Nartac Software to easily turn on and off various protocols, ciphers, hashes, and key exchanges.
Manually editing the report file and using Database - Set Datasource Location when connecting with a more modern native client is one way to fix this so that obsolete and insecure protocols don't need to remain enabled.

Database login prompt when clicked on subreports

I have a report and when clicked on link subreport i get Database login form.I have given all the necessary connection strings but still it asks for login info.sub reports opens in my local system but when installed in Client system i get this problem. what am i missing or what should i do ?
I have found that when setting the database connection in code for a crystal report you need to set the connection on every single table in the report Database Definition. You can do this like:
private static void SetConnectionInfo(ReportClass report, string ReportServer, string ReportDatabase)
{
TableLogOnInfo tInfo = new TableLogOnInfo();
ConnectionInfo connectionInfo = tInfo.ConnectionInfo;
connectionInfo.IntegratedSecurity = true;
connectionInfo.ServerName = ReportServer;
connectionInfo.DatabaseName = ReportDatabase;
foreach (Table t in report.Database.Tables)
{
t.ApplyLogOnInfo(tInfo);
}
foreach (ReportClass subReport in report.Subreports)
{
SetConnectionInfo(subReport, ReportServer, ReportDatabase);
}
}

Categories