I am trying to query my mySQL database and want all rows returning in an array which is accessible in a way like.
rows[0]["column"]
rows[1]["column"].
My code is currently:
MySqlCommand cmd = new MySqlCommand(query, conn);
var dt = new DataTable();
dt.Load(cmd.ExecuteReader());
var rows = dt.AsEnumerable().ToArray();
So I can use rows[0]["column"] but rows[1] is out of reach, as if the dt.Load hasn't scanned all rows and added them to the list.
I give you some pseudo code here, I did not try to compile it but should give you the idea, in general do not use static indexes like "1" to access the second row in the table, better have a loop or some other kind of dynamic approach which would always work no matter on how many records your query returns.
look at this, omitted exception handling for compactness
using(var conn = new MySqlConnection(connectionString))
using(var cmd = conn.CreateCommand())
{
conn.Open();
cmd.ComamndText = query;
var adp = new MySqlDataAdapter(cmd);
var dt = new DataTable();
adp.Fill(dt);
// here you can use the table's rows array to retrieve results
// for example
foreach (var row in dt.Rows)
{
//Do what you want now with this row
}
}
Related
Good day sir and ma'am. I'm planning to get all row header like "column_id and first_name, last_name and so on" and populate my listbox with row header from mysql database table. Please enlighten me how to do this. I am not sure what to use MySqlDataAdapter or MySqlDataReader. I'm beginner and willing to learn.
using (MySqlConnection conns2 = new MySqlConnection(connString))
{
conns2.Open();
MySqlCommand comm2 = new MySqlCommand("SELECT * FROM table1",
conns2);
MySqlDataAdapter add2 = new MySqlDataAdapter(comm2);
DataTable dt2 = new DataTable();
add2.Fill(dt2);
foreach(DataColumn column in dt2.Columns)
{
columnlistbox.Items.Add(dt2.Columns);
//it shows "collection" and exactly the number of row header
//but it doesn't show like "First name, client_id and last
//name"
}
conns2.Close();
}
for get columns names from a DataTable
If you need data from the db, and you load it into a DataTable (using DbDataAdapter or DbDataReader), you can know the column names from the DataTable.Columns collection property:
foreach (DataColumn col in dt2.Columns)
columnlistbox.Items.Add(col.ColumnName);
get only schema from MySql db (tables, columns ect)
but if you not need any data from the DB, but only its structure, you can use the DbDataReader. for load this data by the reader, a query must be "simulated" to the database:
using (MySqlConnection conns2 = new MySqlConnection(connString))
{
conns2.Open();
MySqlCommand comm2 = new MySqlCommand("SELECT * FROM table1", conns2);
using (var reader = MySqlCommand.ExecuteReader(CommandBehavior.SchemaOnly))
{
reader.Read();
var dtSchema = reader.GetSchemaTable();
foreach (DataRow row in tableSchema.Rows)
columnlistbox.Items.Add(row["ColumnName"]);
}
}
form https://stackoverflow.com/a/7159610/1271037:
Using the MySqlDataAdapter is the appropriate choice based on the sample code you provided because you are populating a DataTable and in ADO.NET DataAdapters are traditionally used to populate DataTables. A DataAdapter populates or "fills" your DataTable object.
You could also use a DataReader to populate your DataTable:
var dataReader = cmd.ExecuteReader();
var dataTable = new DataTable();
dataTable.Load(dataReader);
DataAdapters and DataReaders are a core design concept of ADO.NET, whether using Sql Server or MySQL database. A DataReader is a forward only, light and faster Database query helper. A DataAdapter is a bit heavier than a DataReader and also does more than a DataReader can do, it is possible that a DataAdapter uses a DataReader behind the scenes.
Here is how you would use the data from your MySQL database, you need to use a DataGrid, not a ListBox
using (MySqlConnection conn = new MySqlConnection(connString))
{
conn.Open();
MySqlCommand cmd = new MySqlCommand("SELECT * FROM table1",
conn);
MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter.Fill(dt);
//display your dataset in a ASP.NET Web Forms DataGrid
dataGrid.DataSource = dt;
dataGrid.DataBind();
//conn.Close();// you do not need this, your using statements call Dispose and Dispose will release the connection back to the connection pool
}
You can get pointers from this code. In summary GetName is what you are looking for.
using (Common.DbCommand cmd = conn.CreateCommand()) {
cmd.CommandText = "SELECT * FROM table1";
dynamic dr = cmd.ExecuteReader();
int index = 0;
List<string> columns = new List<string>();
for (index = 0; index <= dr.FieldCount - 1; index++) {
columns.Add(dr.GetName(index));
}
}
I am having a strange problem and I have no clue whether it is happening due to bad connection or something else is causing this.
The problem I have a combo box and I am populating the values using SQL Data Table in "Form Load" event and it was working fine until today. Every time the form loaded both the combo boxes are empty one for date and other for company name. The code I am using is below.
public DataTable getResult(string query)
{
SqlDataAdapter da = new SqlDataAdapter();
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand(query, con);
cmd.CommandTimeout = 0;
da.SelectCommand = cmd;
da.Fill(dt);
return dt;
}
private void Reports_Load(object sender, EventArgs e)
{
RevenueDate_dt = func.getResult(dateQuery);
foreach (DataRow dr in RevenueDate_dt.Rows)
{
comboBox1.Items.Add(dr["Global_Period_Month"].ToString());
}
Gpn_dt = func.getResult(GpnQuery);
foreach (DataRow dr in Gpn_dt.Rows)
{
comboBox2.Items.Add(dr["gpnname"].ToString());
}
}
The query showing perfect result when I am executing it on SQL Server.
Looking forward for answers.
It's hard to say what's happening, but I wonder if the datatable isn't a little overkill for what you want. It seems a normal DataReader would have a lot less overhead and would be easier to debug. Something like this:
public string[] getResult(string query, string ColumnName)
{
List<string> results = new List<string>();
SqlCommand cmd = new SqlCommand(query, con);
cmd.CommandTimeout = 0;
SqlDataReader reader = cmd.ExecuteReader();
int col = reader.GetOrdinal(ColumnName);
while (reader.Read())
{
results.Add(reader.GetString(col));
}
reader.Close();
return results.ToArray();
}
And then to add the items to your combo boxes, it would simply look like this:
comboBox1.Items.AddRange(func.getResult(dateQuery, "Global_Period_Month"));
comboBox2.Items.AddRange(func.getResult(GpnQuery, "gpnname"));
What would be the best way of building an empty DataTable based on existing table in SQL server? My current try is this one, which is just retyping this manually, so it is not great, especially for large data sets.
private DataTable createEmptyReadingDataTableReadyToSaveToDb()
{
dtbl.Columns.Add("ProductId", typeof(string));
dtbl.Columns.Add("Price", typeof(float));
dtbl.Columns.Add("Revenue", typeof(float));
dtbl.Columns.Add("URL", typeof(string));
// etc ....
return dtbl;
}
I read today about schemas, which seem natural for this task. It got me more confused than I thought this would be. Anyways such approach below returns a datatable returning broad set of information about the dataset, but I do not find there accessors to get information about the interesting DataTable (below). Probably I do something wrong.
private static DataTable getReadingTableFromSchema()
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
{
string sql = "SELECT * FROM [Readings]";
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader reader = cmd.ExecuteReader();
DataTable dtbl = reader.GetSchemaTable();
return dtbl;
}
}
I could also just try the approach with DataAdapter reading the data, then filling it (basically copying the DataTable) and then deleting all rows to have the table empty - but this would definitely affect the performance. What would be the right solution?
you can use DataAdapter and fill DataTable with full schema:
private static DataTable getReadingTableFromSchema()
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
{
string sql = "SELECT * FROM [Readings]";
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
DbDataAdapter da = new SqlDataAdapter(cmd);
DataTable dtbl = new DataTable();
da.FillSchema(dtbl, SchemaType.Source);
return dtbl;
}
}
And, I suggest you to use "using" for command and adapter too
Using a bit of LINQ
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
{
conn.Open();
using (var reader = new SqlCommand("SELECT * FROM [Readings] WHERE 1 = 0", conn).ExecuteReader())
{
var dataColumns = Enumerable.Range(0, reader.FieldCount)
.Select(i => new DataColumn(reader.GetName(i), reader.GetFieldType(i)))
.ToArray();
var dataTable = new DataTable("Readings");
dataTable.Columns.AddRange(dataColumns);
}
}
I have a table where I am trying to capture all the values in one column across many rows with a matching identifier. For example my query is similar to:
SELECT
prevHours
FROM
submissions
WHERE
projectCat='Capacity'
I am then trying to pass all of the values in prevHours into a single array that I can perform operations on.
The simplest way to work with a list of values from the database is to use a List<T>; the code is similar to what you have now, see below.
The code is quite simple:
var container = new List<int>();
var dbConnection = "...";
var query = "SELECT [prevHours] FROM [submissions] WHERE [projCat] = #Value";
using(var connection = new SqlConnection(dbConnection))
using(var command = new SqlCommand(query, connection))
{
connection.Open();
command.Parameters.Add("#Value", SqlDbType.VarChar, max).Value = "Capacity";
using(var reader = command.ExecuteReader())
while(reader.Read())
{
if(reader["prevHours"] != DBNull.Value)
container.Add(Convert.ToInt32(reader["prevHours"]));
}
}
Additionally, if you are not using the list for further processing, you could use ExecuteScalar and a query of the form
SELECT SUM(prevHours) FROM submissions WHERE projCat = #Value
for similar results using command.ExecuteScalar()
I write a function to return a database table:
public static DataTable ExecuteDataTable(SqlConnection conn, string cmdText,
params SqlParameter[] parameters)
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = cmdText;
cmd.Parameters.AddRange(parameters);
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
}`
I'm trying to take information from my SQL server and load it into a datagridview based on paramaters selected by the user. The example I post at the end of this question worked in an earlier function in the program, but now it isn't. This leads me to believe that the issue lies in the line that actually outputs the data to the DGV. Any thoughts on why it's not filling up the DGV? I've included two examples, neither of which is working. For some reason, they're just not inputting any information into the DGV, even though I know from debugging that they are indeed pulling the information from the server successfully.
SqlConnection DBConnection = new SqlConnection(ConnectionString);
//Opens the connection
DBConnection.Open();
//Creates a string to hold the query
string query = "SELECT * FROM PRD WHERE PRD_NUM LIKE '" +OutputBeforeIncrement + "%'";
//Creates an SQLCommand object to hold the data returned by the query
SqlCommand queryCommand = new SqlCommand(query, DBConnection);
//Uses the aforementioned SQLCommand to create an SQLDataReader object
SqlDataReader queryCommandReader = queryCommand.ExecuteReader();
//Creates a DataTable to hold the data
DataTable dataTable = new DataTable();
//This part actually loads the data from the query into the table
dataTable.Load(queryCommandReader);
dgvOutput.DataSource = dataTable;
The other example:
using (SqlDataAdapter newDA = new SqlDataAdapter(query, DBConnection))
{
DataTable Table = new DataTable();
newDA.Fill(Table);
dgvOutput.DataSource = Table;
}
You might try this or something similar:
SqlDataAdapter myDataAdapter;
SqlCommandBuilder myCommandBuilder;
SqlCommand mySqlCommand = new SqlCommand(myQuery, MySQLConnection);
//I think this is the default command type, and thus can be omitted
mySqlCommand.CommandType = CommandType.Text;
myDataAdapter = new SqlDataAdapter(mySqlCommand);
//Automates your insert/update/delete
myCommandBuilder = new SqlCommandBuilder(myDataAdapter);
myDataAdapter.Fill(myDataTable);
dgvOutput.DataSource = myDataTable.DefaultView;