Symptom
Report was created using a connection to a single data source for both main and subreport.
At runtime we need to set the subreport connection to a different data source using only the ClientDocument, Not using RAS.
Environment
- Crystal Reports for Visual Studio
- BOE 4.x .NET SDK
- Microsoft Visual Studio 2010 or above
Cause
The Report ClientDocument ( Engine ) will propagate the conneciton info from the main report to the subreport and use the same connection info. It will not allow using separate connection properties.
Resolution
There is a specific work that must be followed when changing a single connection to mulitple connections between main and subreport as follows:
- To explain how and why this needs changes is first thing you need to do is create a second DSN to your data base. The reason being the Engine when it detects the same data source being used will propagate the connection info used in the main report to the subreport connection info. To stop this you must use a separate connection source and therefore the reason for the second DSN.
- Now the second part of the changes is having to save the updated subreport connection info first, and also note you must set the subreport connection info first and then save the report as a temp report file.
- Close the report and now open the temp report.
- Now update the connection info for the main report, refresh it and then set the parameter values.
static void Main(string[] args)
{
ReportDocument rd = new ReportDocument();
rd.Load(@"D:\Report\ReportDon.rpt");
//workaround to set sub rpt's connection first, save to disk temp file, load temp file again, then update main rpt's connection
SetSubConnection(rd);
rd.SaveAs(@"D:\Report\temp.rpt");
rd.Close();
rd.Load(@"D:\Report\temp.rpt");
SetMainConnection(rd);
//need refresh report to update data and provide param/db info to export and saveas
rd.Refresh();
SetParameters(rd);
rd.SetDatabaseLogon("sa1", "sybase1");//set main report login to DSN DSN2, userid sa1
//set sub report login to DSN NYTD_RGSDEV, userid sa
for (int i = 0; i < rd.Subreports.Count; i++)
{
rd.Subreports[i].SetDatabaseLogon("sa", "sybase");
}
rd.ExportToDisk(ExportFormatType.PortableDocFormat, @"D:\Report\exported.pdf"); // export the report to PDF
rd.SaveAs(@"D:\Report\ReportDon_2DSN.rpt", true); // save the report if you want it
}
Log on routines:
private static void SetSubConnection(ReportDocument rd)
{
for (int i = 0; i < rd.Subreports.Count; i++)
{
foreach (Table table in rd.Subreports[i].Database.Tables)
{
try
{
TableLogOnInfo logonInfo = table.LogOnInfo;
logonInfo.ConnectionInfo.ServerName = "DSN1";
logonInfo.ConnectionInfo.UserID = "sa1";
logonInfo.ConnectionInfo.Password = "sybase1";
logonInfo.ConnectionInfo.DatabaseName = "don";
logonInfo.TableName = "dbo" + logonInfo.TableName;
table.ApplyLogOnInfo(logonInfo);
table.Location = "dbo" + table.Location;
}
catch (Exception e)
{
throw;
}
}
}
}
private static void SetMainConnection(ReportDocument rd)
{
foreach (Table table in rd.Database.Tables)
{
try
{
TableLogOnInfo logonInfo = table.LogOnInfo;
logonInfo.ConnectionInfo.ServerName = "DSN2";
logonInfo.ConnectionInfo.UserID = "sa";
logonInfo.ConnectionInfo.Password = "sybase";
logonInfo.ConnectionInfo.DatabaseName = "don";
logonInfo.TableName = "dbo" + logonInfo.TableName;
table.ApplyLogOnInfo(logonInfo);
table.Location = "dbo" + table.Location;
}
catch (Exception e)
{
throw;
}
}
}
Set the parameters if required:
private static void SetParameters(ReportDocument rd)
{
ParameterFieldDefinitions parameterFields = rd.DataDefinition.ParameterFields;
parameterFields.Reset();
for (int i = 0; i < parameterFields.Count; i++)
{
ParameterFieldDefinition pf = parameterFields[i];
if (pf.IsLinked())
{
continue;
}
if (pf.CurrentValues.Count == 0) //No saved parameter value
{
if (pf.DefaultValues.Count > 0)// Set report to use LOV pick list value, index 0
{
if (string.IsNullOrEmpty(pf.ReportName))
rd.SetParameterValue(pf.Name, pf.DefaultValues[0]);
else
rd.SetParameterValue(pf.Name, pf.DefaultValues[0], pf.ReportName);
}
else//Directly set parameter value, value 1 for main report and value 0 for subreport
{
if (string.IsNullOrEmpty(pf.ReportName))
rd.SetParameterValue(pf.Name, 1);
else
rd.SetParameterValue(pf.Name, 0, pf.ReportName);
}
}
else //use saved parameter value
{
if (string.IsNullOrEmpty(pf.ReportName))
rd.SetParameterValue(pf.Name, pf.CurrentValues[0]);
else
rd.SetParameterValue(pf.Name, pf.CurrentValues[0], pf.ReportName);
}
}
}
Keywords
cr for vs, clientdocument, datasource, .net sdk , KBA , BI-DEV-NET , BI Software Development Kits (SDKs) - .NET or Other , Problem