Thank you so much Ludek. You are a legend.
That utility helped solve my problem. It generated a piece of code which is a bit different approach than what I had written , it correctly updates the ODBC datasource at runtime. (I have modified the code a bit. The utility generates code specific to report (with table details etc), I have modified it because in my case, I don't know what reports User will be uploading and running.
I will paste my code here in case it helps anyone else.
It all works well now on my machine, will try it on client's soon.
using CrystalDecisions.ReportAppServer.DataDefModel;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
private void ViewCrystalReport()
{
try
{
CrystalDecisions.CrystalReports.Engine.ReportDocument rpt = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
rpt.Load(FullReportPath);
//Create a new Database Table to replace the reports current table.
CrystalDecisions.ReportAppServer.DataDefModel.Table boTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();
//boMainPropertyBag: These hold the attributes of the tables ConnectionInfo object
PropertyBag boMainPropertyBag = new PropertyBag();
//boInnerPropertyBag: These hold the attributes for the QE_LogonProperties
//In the main property bag (boMainPropertyBag)
PropertyBag boInnerPropertyBag = new PropertyBag();
//Set the attributes for the boInnerPropertyBag
boInnerPropertyBag.Add("DSN", "TEST");
boInnerPropertyBag.Add("UseDSNProperties", "False");
//Set the attributes for the boMainPropertyBag
boMainPropertyBag.Add("Database DLL", "crdb_odbc.dll");
boMainPropertyBag.Add("QE_DatabaseName", "");
boMainPropertyBag.Add("QE_DatabaseType", "ODBC (RDO)");
//Add the QE_LogonProperties we set in the boInnerPropertyBag Object
boMainPropertyBag.Add("QE_LogonProperties", boInnerPropertyBag);
boMainPropertyBag.Add("QE_ServerDescription", "TEST");
boMainPropertyBag.Add("QE_SQLDB", "True");
boMainPropertyBag.Add("SSO Enabled", "False");
//Create a new ConnectionInfo object
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo boConnectionInfo =
new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
//Pass the database properties to a connection info object
boConnectionInfo.Attributes = boMainPropertyBag;
//Set the connection kind
boConnectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
//**EDIT** Set the User Name and Password if required.
boConnectionInfo.UserName = "TEST";
boConnectionInfo.Password = "TEST";
//Pass the connection information to the table
boTable.ConnectionInfo = boConnectionInfo;
//Get the Database Tables Collection for your report
CrystalDecisions.ReportAppServer.DataDefModel.Tables boTables;
boTables = rpt.ReportClientDocument.DatabaseController.Database.Tables;
//For each table in the report:
// - Set the Table Name properties.
// - Set the table location in the report to use the new modified table
for (int i = 0; i < boTables.Count; i++)
{
boTable.Name = rpt.ReportClientDocument.DatabaseController.Database.Tables[i].Name;
boTable.QualifiedName = rpt.ReportClientDocument.DatabaseController.Database.Tables[i].QualifiedName;
boTable.Alias = rpt.ReportClientDocument.DatabaseController.Database.Tables[i].Alias;
rpt.ReportClientDocument.DatabaseController.SetTableLocation(boTables[i], boTable);
}
//Verify the database after adding substituting the new table.
//To ensure that the table updates properly when adding Command tables or Stored Procedures.
rpt.VerifyDatabase();
//Simply display Report in Report Viewer
CrystalReportViewer2.ReportSource = rpt;
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
}