You first have to set your Crystal Report to use an ADO.NET schema. (see image below). To generate the schema you just create a data set and create tables to fill it. Once filled add your tables (with table names to the data set) then you can export the schema to an xml file.
List<Tuple<string, string>> sqlQueries = new List<Tuple<string, string>>();
// The sql queries below shoudl match the same column names
// you want to pull back from the database for yoru report
sqlQueries.Add(new Tuple<string, string>("Table1Name", "SELECT TOP 1 .... FROM ..."));
sqlQueries.Add(new Tuple<string, string>("SubReportName", "SELECT TOP 1 .... FROM ..."));
sqlQueries.Add(new Tuple<string, string>("SubReport2TableName", "SELECT TOP 1 .... FROM ..."));
SqlConnection connection = new SqlConnection(ConnectionString);
DataSet resultSet = new DataSet();
foreach (var tuple in sqlQueries)
{
SqlDataAdapter adapter = new SqlDataAdapter(tuple.Item1, connection);
DataTable schema = new DataTable();
adapter.Fill(schema);
schema.TableName = tuple.Item2;
resultSet.Tables.Add(schema);
}
// write out the schema to a file
string path = Path.Combine("PATH_TO_DATASET_XML.xml");
using (var writer = File.CreateText(path))
{
writer.Write(resultSet.GetXmlSchema().Replace(" encoding=\"utf-16\"", ""));
}
Next use that as a your data source in Crystal Reports
Finally just use the same xml file to fill your report data:
DataSet reportData = new DataSet();
SqlConnection connection = new SqlConnection();
SqlDataAdapter reportAdapter = new SqlDataAdapter();
reportAdapter.SelectCommand = new SqlCommand();
reportAdapter.SelectCommand.Connection = connection;
reportData.ReadXml("PATH_TO_DATASET_XML.xml");
List<Tuple<string, string>> sqlQueries = new List<Tuple<string, string>>();
sqlQueries.Add(new Tuple<string, string>("Table1Name", "SELECT .... FROM ..."));
sqlQueries.Add(new Tuple<string, string>("SubReportName", "SELECT .... FROM ..."));
sqlQueries.Add(new Tuple<string, string>("SubReport2TableName", "SELECT .... FROM ..."));
reportData.EnforceConstraints = false;
foreach (var tuple in sqlQueries)
{
reportAdapter.SelectCommand.CommandText = tuple.Item1;
try
{
reportAdapter.Fill(reportData, tuple.Item2.Trim());
}
catch (Exception ex)
{
// Handle your stuff
}
}
using (var exportReport = new ReportDocument())
{
exportReport.Load("PATH_TO_RPT_FILE.rpt");
exportReport.SetDataSource(reportData);
// export report to wherever you want
}