What I'm trying to do is run the same SQL select on many Oracle databases (at least a dozen), and display the output in a Gridview.
I've hacked together something that works but unfortunately it's very slow. I think its exacerbated by the fact that at least 1 of the dozen databases will invariably be unreachable or otherwise in an error state.
As well as being slow I can't help thinking it's not the best way of doing it, nor very '.NET' like.
I've written something similar in the past as a simple loop in PHP that just connects to each db in turn, runs the sql and writes another <tr>
, and it works at least twice as fast, for a given query. But I'm not really happy with that, I'd like to improve my knowledge!
I'm learning C# and ASP.NET so please excuse the horrible code :)
public void BindData(string mySQL)
{
OracleConnection myConnection;
OracleDataAdapter TempDataAdapter;
DataSet MainDataSet = new DataSet();
DataTable MainDataTable = new DataTable();
DataSet TempDataSet;
DataTable TempDataTable;
string connectionString = "";
Label1.Visible = false;
Label1.Text = "";
foreach (ListItem li in CheckBoxList1.Items)
{
if (li.Selected)
{
connectionString = "Data Source=" + li.Text + "";
connectionString += ";Persist Security Info=True;User ID=user;Password=pass;Unicode=True";
myConnection = new OracleConnection(connectionString);
try
{
TempDataAdapter = new OracleDataAdapter(mySQL, myConnection);
TempDataSet = new DataSet();
TempDataTable = new DataTable();
TempDataAdapter.Fill(TempDataSet);
TempDataTable = TempDataSet.Tables[0].Copy();
/* If the main dataset is empty, create a table by cloning from temp dataset, otherwise
copy all rows to existing table.*/
if (MainDataSet.Tables.Count == 0)
{
MainDataSet.Tables.Add(TempDataTable);
MainDataTable = MainDataSet.Tables[0];
}
else
{
foreach (DataRow dr in TempDataTable.Rows)
{
MainDataTable.ImportRow(dr);
}
}
}
catch (OracleException e)
{
Label1.Visible = true;
Label1.Text = Label1.Text + e.Message + " on " + li.Text + "<br>";
}
finally
{
if (myConnection != null)
{
myConnection.Close();
myConnection = null;
}
TempDataSet = null;
TempDataAdapter = null;
TempDataTable = null;
}
}
}
GridView1.DataSourceID = String.Empty;
if (MainDataSet.Tables.Count != 0)
{
GridView1.DataSource = MainDataSet;
if (GridView1.DataSource != null)
{
GridView1.DataBind();
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
BindData(TextBox1.Text);
}
Thanks!
UPDATE: The SQL code varies, for testing I have used very simple queries such as select sysdate from dual
or select name from v$database
. In eventual use, it will be much more complicated, the idea is that I should be able to run pretty much anything, hence the BindData(TextBox1.Text)
UPDATE: The reason for connecting to many databases from the ASP.NET code rather than a stored proc on one or all dbs, or replicating to one db, is twofold. Firstly, the dbs in question are frequently updated replicas of several similar production environments (typically development, testing and support for each client), so anything done to the actual dbs would have to be updated or redone regularly as they are reloaded anyway. Secondly, I don't know in advance what kind of query might be run, this form lets me just type e.g. select count (name) from dbusers
against a dozen databases without having to first think about replicating the dbusers table to a master db.