I have spent quite some effort trying to get round this. In the end I removed the link between the main report and sub report parameters. This then allows me to provide the parameter values to the viewer. And it makes the problem go away.
I use the viewer instead of the sub report because I had problems setting the parametr to the sub report and with the viewer I can just use the numeric index of parameters.
The underlying problem is therefore that pointing at a different database from design time must also need some change to the link. So my method is far from ideal but delivery date was yesterday...
// Note
// There is an outstanding issue with this code
// I had to break the link between the subreport and main report to get it to work
ReportDocument rd, rdsub;
rd = new ReportDocument();
rd.Load(Server.MapPath("Reports\\Risk_Assessment.rpt"), CrystalDecisions.Shared.OpenReportMethod.OpenReportByTempCopy);
// Switch database
Sections crSections;
SubreportObject crSubreportObject;
ReportObjects crReportObjects;
Database crDatabase;
Tables crTables;
TableLogOnInfo crTableLogOnInfo;
crDatabase = rd.Database;
crTables = crDatabase.Tables;
ConnectionInfo crConn = new ConnectionInfo();
crConn.ServerName = DB.ServerString;
crConn.DatabaseName = "RiskMan";
crConn.UserID = DB.ServerUser;
crConn.Password = DB.ServerPassword;
crConn.IntegratedSecurity = false;
foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables)
{
crTableLogOnInfo = aTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = crConn;
aTable.ApplyLogOnInfo(crTableLogOnInfo);
//aTable.Location = crConn.DatabaseName + ".dbo." + aTable.Location.Substring(aTable.Location.LastIndexOf(".") + 1);
}
// THIS STUFF HERE IS FOR REPORTS HAVING SUBREPORTS
// set the sections object to the current report's section
crSections = rd.ReportDefinition.Sections;
// loop through all the sections to find all the report objects
foreach (Section crSection in crSections)
{
crReportObjects = crSection.ReportObjects;
//loop through all the report objects in there to find all subreports
foreach (ReportObject crReportObject in crReportObjects)
{
if (crReportObject.Kind == ReportObjectKind.SubreportObject)
{
crSubreportObject = (SubreportObject)crReportObject;
//open the subreport object and logon as for the general report
rdsub = crSubreportObject.OpenSubreport(crSubreportObject.SubreportName);
crDatabase = rdsub.Database;
crTables = crDatabase.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables)
{
crTableLogOnInfo = aTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = crConn;
aTable.ApplyLogOnInfo(crTableLogOnInfo);
//aTable.Location = crConn.DatabaseName + ".dbo." + aTable.Location.Substring(aTable.Location.LastIndexOf(".") + 1);
}
}
}
}
crvRisk.ReportSource = rd;
ParameterFields crParameterFields;
ParameterField crParameterField;
ParameterValues crParameterValues;
ParameterDiscreteValue crParameterDiscreteValue;
//Get the collection of parameters from the report
crParameterFields = crvRisk.ParameterFieldInfo;
crParameterField = crParameterFields[0];
crParameterValues = crParameterField.CurrentValues;
crParameterDiscreteValue = new ParameterDiscreteValue();
crParameterDiscreteValue.Value = Session["Default_Risk"];
crParameterValues.Add(crParameterDiscreteValue);
crParameterDiscreteValue = null;
crParameterField = crParameterFields[1];
crParameterValues = crParameterField.CurrentValues;
crParameterDiscreteValue = new ParameterDiscreteValue();
crParameterDiscreteValue.Value = Session["Default_Risk"];
crParameterValues.Add(crParameterDiscreteValue);
//Set the modified parameters collection back to the viewer so that
//the new parameter information can be used for the report.
crvRisk.ParameterFieldInfo = crParameterFields;
crvRisk.DisplayGroupTree = false;