I have 21 tables in Oracle 11g, and I need to display them using JOIN clauses. But the query is too slow and throws an System.OutOfMemoryException
My current code:
try
{
//string ConString;
using (OracleConnection con = new OracleConnection(ConString))
{
//string query = "SELECT PAX.CREATION_DATE,PAX.PNR,PAX.PAX_NMBR,PAX.UPDATE_LEVEL_MOD,PAX.PAX_NAME,PAX.CHANGE_OR_CANCEL_IND,PAX_SEATS.LEG_NMBR,PAX_SEATS.INSTANCE_NMBR,pax_seats.ssr_cd,pax_seats.carrier_cd,pax_seats.seat_nmbr,pax_seats.previous_status_codes FROM PAX INNER JOIN PAX_SEATS ON PAX.PNR = PAX_SEATS.PNR";
string query1 = "SELECT PNR FROM HISTORY_LEGS";
string query2 = "SELECT PAX.CREATION_DATE,PAX.PNR,PAX.PAX_NMBR,PAX.UPDATE_LEVEL_MOD,PAX.PAX_NAME,PAX.CHANGE_OR_CANCEL_IND,PAX_SEATS.LEG_NMBR,PAX_SEATS.INSTANCE_NMBR,pax_seats.ssr_cd,pax_seats.carrier_cd,pax_seats.seat_nmbr,pax_seats.previous_status_codes,PAX_SSRS.SSR_NMBR,PAX_TKT.TKTNMBR,PAX_TKT.ISSUING_AIRLINE, PAX_TKT.ISSUING_OFFC_NMBR, PAX_TKT.ISSUING_COUNTER_CD, PAX_TKT.ISSUING_AGNT_NMBR, PAX_TKT.TKT_IND, PAX_TKT.TKT_STATUS, PAX_TKT.TARIFICATION_IND,PAX_TKT.S_IND,PAX_TKT.ISSUANCE_DATE FROM PAX INNER JOIN PAX_SEATS ON PAX.PNR = PAX_SEATS.PNR RIGHT JOIN PAX_SSRS ON PAX.PNR = PAX_SSRS.PNR RIGHT JOIN PAX_TKT ON PAX.PNR = PAX_TKT.PNR";
//string query4 = "SELECT * FROM PAX";
//string query3 = "SELECT PAX.PAX_NMBR,PAX.PAX_NAME,RES_LEGS.ARNK_IND,RES_LEGS.CARRIER_CD1,RES_LEGS.CARRIER_CD2,RES_LEGS.FLT_NMBR,RES_LEGS.CLASS_CD,RES_LEGS.DAY_OF_WEEK,RES_LEGS.FLT_DATE,RES_LEGS.LEG_ORIGIN_CD,RES_LEGS.LEG_DES_CD,RES_LEGS.CURRENT_STATUS_CD,RES_LEGS.NUMBER_IN_PARTY,RES_LEGS.DP_TIME,RES_LEGS.AR_TIME,RES_LEGS.DATE_CHANGE_IND,RES_LEGS.FLT_IRREGULARITY_IND,RES_LEGS.LEG_TXT,RES_LEGS.PREVIOUS_STATUS_CODES,RES_LEGS.MESSAGE FROM RES_LEGS INNER JOIN PAX ON RES_LEGS.PNR = PAX.PNR";
OracleCommand cmd = new OracleCommand(query2, con);
OracleDataAdapter oda = new OracleDataAdapter(cmd);
DataSet ds = new DataSet();
oda.Fill(ds);
//dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.EnableResizing;
//dataGridView1.RowHeadersVisible = false;
if (ds.Tables.Count > 0)
{
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Questions:
How to get all data?
How to prevent System.OutofMemory?
How to speed up query execution performance?
You can look at indexes on your key fields to speed up the query a bit perhaps, but if you are getting a lot of rows back you'll be hitting some memory caps somewhere.
If you can, I would suggest implementing some paging: Paging with Oracle.
This will let you bring back smaller chunks of your data making it quicker and less likely to hit any memory limits.
Related
MySqlConnection con = GetConnection();
string sql = "SELECT COUNT(ID) FROM booking WHERE DATE(Booking_Date) = CURDATE()";
string sql2 = "SELECT SUM(Fare) FROM booking WHERE DATE(Booking_Date) = CURDATE()";
MySqlCommand cmd = new MySqlCommand(sql, con);
cmd.CommandType = System.Data.CommandType.Text;
MySqlDataReader BookingToday = cmd.ExecuteReader();
while (BookingToday.Read())
{
label6.Text = BookingToday.GetValue(0).ToString();
}
This is my C# code and I want to run both the given queries to get result at once. But I don't know how to run multiple data readers on single connection or run 2 connections at once. Anyone please help me in this regard
You can use one query:
string sql = "SELECT COUNT(ID), SUM(Fare) FROM booking WHERE DATE(Booking_Date) = CURDATE()";
In this specific case: you don't need to - you can use the code shown in slaakso's answer to perform both aggregates in one query.
In the more general case:
using (var reader = cmd1.ExecuteReader())
{
// while .Read(), etc
}
using (var reader = cmd2.ExecuteReader())
{
// while .Read(), etc
}
i.e. sequentially and not overlapping (unless your provider supports the equivalent of "MARS").
You can also often issue multiple queries (select) in a single command; you use NextResult() to move between them:
using (var reader = cmd.ExecuteReader())
{
// while .Read(), etc, first grid
if (reader.NextResult())
{
// while .Read(), etc, second grid
}
}
You can't open multiple data readers simultaneously from a single connection.
If you want a single result, you can use ExecuteScalar.
var result1 = (DateTime)new MySqlCommand("select now()", con).ExecuteScalar();
Console.WriteLine(result1);
var result2 = (DateTime)new MySqlCommand("select date_add(now(), interval 10 day)", con).ExecuteScalar();
Console.WriteLine(result2);
For multi-row results, you can store them in a DataTable.
var dt1 = new DataTable();
dt1.Load(new MySqlCommand("select id from table1", con).ExecuteReader());
var dt2 = new DataTable();
dt2.Load(new MySqlCommand("select name from table1", con).ExecuteReader());
foreach(var row in dt1.AsEnumerable())
{
Console.WriteLine($"id:{row["id"]}");
}
foreach (var row in dt2.AsEnumerable())
{
Console.WriteLine($"name:{row["name"]}");
}
Hello I have an error on this c# code,I have an exception on code: MessageBox.Show("Salto sulla query 3 "+ex), but I can not understand why, I loaded the exception image that is generated below,can you help me thanks.
MessageBox.Show("Aggiorno Articoli ");
//APRO LA CONNESSIONE AL FILE
dbConn = new OleDbConnection(#"Provider = Microsoft.Jet.OLEDB.4.0; Data Source=" + dialog.FileName + "; Persist Security Info = False; Jet OLEDB:Database Password = " + textBoxPwdComet.Text + "; Mode = Share Deny None");
//APRO LA CONNESSIONE
SqlConnection conn = db.apriconnessione();
//CREO LA TABELLA TEMPORANEA
String QueryTemp = "CREATE TABLE TabellaTemp(CODMARCA varchar(MAX),CODART varchar(MAX),DESCR varchar(MAX),UM varchar(MAX),PRZNETTO money,PRZCASA money,DATAAGG datetime,);";
SqlCommand cmdTemp = new SqlCommand(QueryTemp, conn);
cmdTemp.ExecuteNonQuery();
//COPIA DEI DATI NELLA TABELLA TEMPORANEA
string query = "SELECT CODMARCA,CODART,DESCR,UM,PRZNETTO,PRZCASA,DATAAGG FROM ARTICOLI";
OleDbDataAdapter da = new OleDbDataAdapter(query, dbConn);
DataTable dt = new DataTable();
da.Fill(dt);
SqlBulkCopy bulk = new SqlBulkCopy(conn);
bulk.DestinationTableName = "TabellaTemp";
bulk.WriteToServer(dt);
//Setto tutti gli articoli come non disponbili(QUELLI COMET)
try
{
String Query2 = "Update Articolo set Stato = 'Nondisponibile' where Importato = 'COMET' ";
cmdTemp = new SqlCommand(Query2, conn);
cmdTemp.ExecuteNonQuery();
}
catch(Exception ex)
{
MessageBox.Show("Salto su query 2");
}
//Aggiorno gli articoli, quelli che non vengono aggiornati non sono piĆ¹ disponbili
try {
String Query3 = "Update Articolo set Articolo.Stato = 'Disponibile',Articolo.Prezzo = TabellaTemp.PRZNETTO,Articolo.PrezzoListino = TabellaTemp.PRZCASA,Articolo.DataAggiornamento = TabellaTemp.DATAAGG,Articolo.Descrizione = TabellaTemp.DESCR,Articolo.UM = TabellaTemp.UM from Articolo inner join TabellaTemp on TabellaTemp.CodMarca = Articolo.CodMarca and TabellaTemp.CODART = Articolo.CodArt where Articolo.Importato = 'COMET' ";
cmdTemp = new SqlCommand(Query3, conn);
cmdTemp.ExecuteNonQuery();
}
catch(Exception ex)
{
MessageBox.Show("Salto sulla query 3 "+ex);
}
//FINE COPIA DATI TABELLA TEMPORANEA
//ELIMINO LA TABELLA TEMPORANEA
QueryTemp = "DROP TABLE TabellaTemp";
cmdTemp = new SqlCommand(QueryTemp, conn);
cmdTemp.ExecuteNonQuery();
//FINE
conn.Close();
MessageBox.Show("Aggiornamento Articoli terminato!! ");
CaricamentoDataGridNonDisponbili();
Exception:
Your query is timing out ie: not completing in default 30 second. Setting the CommandTimeout to higher value is not a good practice. To actually fix this, you need to provide the table schema (indexing if any) for all the table involved. Based on that you need to optimize your query to run faster using proper indexing.
First try setting your command object to nothing.
cmdTemp = Nothing;
If that doesn't fix it, then try investigating why your update query for query 3 is timing out. I would first convert your UPDATE statement into a SELECT statement. Verify that you are getting results, and that you aren't taxing the server with your query.
SELECT a.Stato, a.Prezzo, a.PrezzoListino, a.DataAggiornamento, a.Descrizione, a.UM,
t.PRZNETTO, t.PRZCASA, t.DATAAGG, t.DESCR, t.UM
FROM Articolo a
INNER JOIN TabellaTemp t on t.CodMarca = a.CodMarca
and t.CODART = a.CodArt
WHERE a.Importato = 'COMET'
If your SELECT statement is working properly, then I'm betting your UPDATE needs more time to run. I believe the timeout property for your command is 30 seconds. You could default this to 0 to run for as long as you wanted, but I would be careful on doing that. Try toying around with the timeout statement. This should fix things up for you.
String Query3 = "Update Articolo set Articolo.Stato = 'Disponibile',Articolo.Prezzo = TabellaTemp.PRZNETTO,Articolo.PrezzoListino = TabellaTemp.PRZCASA,Articolo.DataAggiornamento = TabellaTemp.DATAAGG,Articolo.Descrizione = TabellaTemp.DESCR,Articolo.UM = TabellaTemp.UM from Articolo inner join TabellaTemp on TabellaTemp.CodMarca = Articolo.CodMarca and TabellaTemp.CODART = Articolo.CodArt where Articolo.Importato = 'COMET' ";
cmdTemp = Nothing;
cmdTemp = new SqlCommand(Query3, conn);
// Setting command timeout to 2 minutes
cmdTemp.CommandTimeout = 120;
cmdTemp.ExecuteNonQuery();
I would honestly work on getting your UPDATE statement running at a more optimal speed if this fixes things.
So I have 3 different tables in a MySQL Database called "MyDB", the tables inside are table1, table2, table3. Here is my code to query the 3 tables in the database but it keeps breaking and I can't figure out why. Creating this for a Google Maps Javascript API v3.
private static IEnumerable<HeatMapDataElement> QueryHeatMapDataFromDatabase(string reqDate, string reportType)
{
const string connectionString = "connection_credentials";
var ds = new DataSet();
var elements = new List<HeatMapDataElement>();
var conn = new MySqlConnection(connectionString);
MySqlCommand cmd;
var da = new MySqlDataAdapter();
conn.Open();
try
{
cmd = conn.CreateCommand();
cmd.CommandTimeout = 30;
cmd.CommandText =
"select RequestHour, longitude, latitude, count(requesttime) as Weight from MyDB.table1 || MyDB.table2 || MyDB.table3 where method=#ReportType and requestdate = date(#RequestDate) and longitude is not null and latitude is not null and requesthour is not null group by RequestHour, longitude, latitude";
cmd.Parameters.AddWithValue("#ReportType", reportType);
cmd.Parameters.AddWithValue("#RequestDate", reqDate);
da.SelectCommand = cmd;
da.Fill(ds);
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
elements.AddRange(from DataRow dr in ds.Tables[0].Rows
select new HeatMapDataElement()
{
Latitude = Double.Parse(dr["latitude"].ToString()), Longitude = Double.Parse(dr["longitude"].ToString()), Hour = int.Parse(dr["RequestHour"].ToString()), Weight = int.Parse(dr["Weight"].ToString())
});
}
}
catch (Exception ex)
{
throw ex; //breaks here <-------
}
finally
{
conn.Close();
da = null;
cmd = null;
}
return elements.AsEnumerable();
}
Error is: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '|| MyDB.table2 where method='Table 2' and requestdate =' at line 1
You're mixing up C# code and SQL code. AFAIK pipe operator can only be used in mysql to join columns not tables, and even then, it's disabled by default, so I think that you need to use INNER JOIN
If you're reading from 3 tables you would do an inner join between the 3 tables, something like this:
select * from table1 inner join table2 on table1.key = table2.key
I want to perform a simple search using the SQL LIKE function. Unfortunately for some reason , it doesn't seem to be working. Below is my code.
private void gvbind()
{
connection.Open();
string sql = "";
if (txtSearch.Text.Trim() == "")
{
sql = "SELECT a.cname,[bid],b.[bname],b.[baddress],b.[bcity],b.[bstate],b.[bpostcode],b.[bphone],b.[bfax],b.[bemail] FROM [CLIENT] a INNER JOIN [BRANCH] b ON a.clientID=b.clientID ORDER BY a.[clientID]";
}
else
{
sql = "SELECT a.cname,[bid],b.[bname],b.[baddress],b.[bcity],b.[bstate],b.[bpostcode],b.[bphone],b.[bfax],b.[bemail] FROM [CLIENT] a INNER JOIN [BRANCH] b ON a.clientID=b.clientID WHERE b.[bname] LIKE '%#search%' ORDER BY a.[clientID]";
}
SqlCommand cmd = new SqlCommand(sql,connection);
cmd.Parameters.AddWithValue("#search", txtSearch.Text.Trim());
cmd.CommandType = CommandType.Text;
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = cmd;
DataSet ds = new DataSet();
adp.Fill(ds);
connection.Close();
if (ds.Tables[0].Rows.Count > 0)
{
gvBranch.Enabled = true;
gvBranch.DataSource = ds;
gvBranch.DataBind();
}
else
{
ds.Tables[0].Rows.Add(ds.Tables[0].NewRow());
ds.Tables[0].Rows.Add(ds.Tables[0].NewRow());
gvBranch.DataSource = ds;
gvBranch.DataBind();
int columncount = gvBranch.Rows[0].Cells.Count;
gvBranch.Rows[0].Cells.Clear();
gvBranch.Rows[0].Cells.Add(new TableCell());
gvBranch.Rows[0].Cells[0].ColumnSpan = columncount;
gvBranch.Rows[0].Cells[0].Text = "No Records Found";
}
ds.Dispose();
}
the above method is called in the Page_Load() method using
if((!Page.IsPostBack))
{
gvBind();
}
it is called on button search click aslo. However, it return No record found when ever i perform the search.
Use
LIKE '%' + #search + '%'
instead of
LIKE '%#search%'
Full query;
...
else
{
sql = "SELECT a.cname,[bid],b.[bname],b.[baddress],b.[bcity],b.[bstate],b.[bpostcode],b.[bphone],b.[bfax],b.[bemail] FROM [CLIENT] a INNER JOIN [BRANCH] b ON a.clientID=b.clientID WHERE b.[bname] LIKE '%' + #search + '%' ORDER BY a.[clientID]";
}
And actually, you don't need to use square brackets ([]) every column in your query. Use them if your identifiers or object names are a reserved keyword.
Thanks. It works , but any explanation for that?
The main problem is here, your query parameter is inside quotes. In quotes, SQL Server will recognize it as a string literal and never sees it as a parameter.
Hello i have a method which reads some data from the sql and saves them to arrays.
to find out how many rows the sql result has i wrote this:
DataTable dt = new DataTable();
dt.Load(rdr);
count = dt.Rows.Count;
after that, the sqldatareader saves the results to arrays.
here is my complete code:
public BookingUpdate[] getBookingUpdates(string token)
{
String command = "SELECT b.ID,b.VERANSTALTER, rr.VON ,rr.BIS, b.THEMA, b.STORNO, ra.BEZEICHNUNG from BUCHUNG b JOIN RESERVIERUNGRAUM rr on rr.BUCHUNG_ID = b.ID JOIN RAUM ra on ra.ID = rr.RAUM_ID WHERE b.UPDATE_DATE BETWEEN DATEADD (DAY , -20 , getdate()) AND getdate() AND b.BOOKVERNR = 0";
SqlConnection connection = new SqlConnection(GetConnectionString());
BookingUpdate[] bookingupdate = new BookingUpdate[1];
connection.Open();
try
{
SqlCommand cmd = new SqlCommand(command, connection);
SqlDataReader rdr = null;
int count = 0;
int c = 0;
rdr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(rdr);
count = dt.Rows.Count;
bookingupdate = new BookingUpdate[count];
while (rdr.Read()) // <--- HERE COMES THE ERROR
{
bookingupdate[c] = new BookingUpdate();
bookingupdate[c].bookingID = Convert.ToInt32(rdr["ID"]);
bookingupdate[c].fullUserName = rdr["VERANSTALTER"].ToString();
bookingupdate[c].newStart = (DateTime)rdr["VON"];
bookingupdate[c].newEnd = (DateTime)rdr["BIS"];
bookingupdate[c].newSubject = rdr["THEMA"].ToString();
bookingupdate[c].newlocation = rdr["BEZEICHNUNG"].ToString();
if (rdr["STORNO"].ToString() != null)
{
bookingupdate[c].deleted = true;
}
else
{
bookingupdate[c].deleted = false;
}
c++;
}
}
catch (Exception ex)
{
log.Error(ex.Message + "\n\rStackTrace:\n\r" + ex.StackTrace);
}
finally
{
connection.Close();
}
return bookingupdate;
}
the exeption is : Invalid attempt to call Read when reader is closed
The Load-Method closes the DataReader, hence a following call to Read() fails (well, that's excatly what the exception tells you).
Once you read the data into your DataTable, you could simply query it and use a Select projection to create your BookingUpdate instances (no need for the while-loop/BookingUpdate[]). So your code can basically trimmed down to
String command = "SELECT b.ID,b.VERANSTALTER, rr.VON ,rr.BIS, b.THEMA, b.STORNO, ra.BEZEICHNUNG from BUCHUNG b JOIN RESERVIERUNGRAUM rr on rr.BUCHUNG_ID = b.ID JOIN RAUM ra on ra.ID = rr.RAUM_ID WHERE b.UPDATE_DATE BETWEEN DATEADD (DAY , -20 , getdate()) AND getdate() AND b.BOOKVERNR = 0";
SqlCommand cmd = new SqlCommand(command, new SqlConnection(GetConnectionString()));
connection.Open();
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
var bookingupdate = dt.Rows.OfType<DataRow>().Select (row =>
new BookingUpdate
{
bookingID = Convert.ToInt32(row["ID"]),
fullUserName = row["VERANSTALTER"].ToString(),
newStart = (DateTime)row["VON"],
newEnd = (DateTime)row["BIS"],
newSubject = row["THEMA"].ToString(),
newlocation = row["BEZEICHNUNG"].ToString(),
deleted = row["STORNO"].ToString() != null // note that this line makes no sense. If you can call `ToString` on an object, it is not 'null'
}).ToArray();
return bookingupdate;
(Note: I omited the try-block for readability)
You may also want to look into the DataRowExtensions, especially the Field method, to make your code more readable.
DataTable.Load(IDataReader) closes reader after loading data from it. Use DataTable to get data you loaded.
You have already processed the reader at the following line due to which reader is at EOF/Closed:
dt.Load(rdr);
If you want to process the records after above method call, you should make use of your created DataTable object dt by above line unsing for loop with dt.Rows.Count instead of while (rdr.Read())
Checkout this topic from MSDN