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));
}
}
Related
I am trying to edit a cell in a RadGridView which has a datasource set from data from an SQL view.
What I was hoping to do was to populate the grid from the view, allow edits then manually update the associated tables when a user click an "Update" button.
As soon as the user enters data into a cell and leaves the cell is presents with an error "Specified method is not supported".
I assume it's trying to update the datasource with the new value so I am trying to work out how to tell it not to.
I am populating the table with:
using (SqlConnection con = new SqlConnection(mydatasource))
{
con.Open();
SqlCommand cmd = new SqlCommand("select SRID, Name, Result from EditBatchResultsView where SRID = " + drpSRID.Text, con);
SqlDataReader reader = cmd.ExecuteReader();
radGridView1.DataSource = reader;
}
According to RadGrid data binding documentation, the DataSource property accepts instances of the following types:
DataSet
DataTable
DataView
Array of DataRow
Any object collection that implements these interfaces:
IListSource
IList
IEnumerable
ICustomTypeDescriptor
Based from reference inspection, SqlDataReader doesn't supported because it doesn't implement those interfaces mentioned above, hence NotSupportedException has thrown when binding SqlDataReader contents into DataSource property directly.
As a workaround, you may create new DataTable instance and fill its contents from SqlDataReader like this:
var dt = new DataTable();
using (SqlConnection con = new SqlConnection(mydatasource))
{
con.Open();
SqlCommand cmd = new SqlCommand("select SRID, Name, Result from EditBatchResultsView where SRID = " + drpSRID.Text, con);
SqlDataReader reader = cmd.ExecuteReader();
// fill DataTable contents
dt.Load(reader);
// assign DataTable as data source instead
radGridView1.DataSource = dt;
}
// DataBind goes here
Note:
The string concatenation to build SQL query may prone to SQL injection. Using parameters when passing server control value to SQL query is more recommended way:
var dt = new DataTable();
using (SqlConnection con = new SqlConnection(mydatasource))
{
con.Open();
SqlCommand cmd = new SqlCommand("select SRID, Name, Result from EditBatchResultsView where SRID = #SRID", con);
cmd.Parameters.Add("#SRID", SqlDbType.VarChar).Value = drpSRID.Text;
SqlDataReader reader = cmd.ExecuteReader();
// fill DataTable contents
dt.Load(reader);
// assign DataTable as data source instead
radGridView1.DataSource = dt;
}
Related issue:
Populate data table from data reader
I have a dataGridView that loads its data from an SQL server with the Data Source utility:
However when I trigger the following code:
using (var conn = new SqlConnection(connectionString))
{
string sql = "SELECT * FROM AssetManagement_copy";
using (var cmd = new SqlCommand(sql, conn))
{
sda = new SqlDataAdapter(cmd);
sda.Fill(filteredTable);
dataGridView1.DataSource = filteredTable;
}
}
The Serial No. column of the dataGridView loses its data?
Any ideas as to why this might be happening? I don't do any specific column manipulation or specify any dataColumn in the code to do anything with.
Thanks all!
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 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
}
}
I'm trying to design a method to allow me to take a row from a SQL database using a SELECT. I then want to INSERT the returned row into an identical table on a database which resides on a different server.
My server connection and SELECT statement both work; I can view the row I want copied in a console window.
The issue I'm having is figuring out what data structure I need to use in C#, how to populate this data structure with the SELECT, and finally how to use that data structure to INSERT the row.
I'd like to keep the option for multiple rows open, but for now if I could get a single row transferring across it would be fantastic.
Thank you.
Edit: I've been able to work through this myself after a bunch of research. I've included my code below in the heop it helps someone else, but although it works, it is far from ideal. I am an amateur and it is not yet complete.
static public void CopyDatabaseRows(string ConnectionStringDEV, string ConnectionStringLOCAL, string queryString)
{
//Connect to first database table to retreive row/rows and populate dataset + datatable.
DataSet dataSet = new DataSet();
SqlConnection conn = new SqlConnection(ConnectionStringDEV);
conn.Open();
SqlCommand command = new SqlCommand(queryString, conn);
DataTable dataTable = new DataTable();
SqlDataAdapter dataAdapter = new SqlDataAdapter(queryString, conn);
dataAdapter.FillSchema(dataSet, SchemaType.Mapped);
dataAdapter.Fill(dataSet, "dbo.FileRegister");
dataTable = dataSet.Tables["dbo.FileRegister"];
conn.Close();
//Connect to second Database and Insert row/rows.
SqlConnection conn2 = new SqlConnection(ConnectionStringLOCAL);
conn2.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn2);
bulkCopy.DestinationTableName = "dbo.FileRegister";
bulkCopy.WriteToServer(dataTable);
}
I'd suggest you use something like Simple.Data (https://github.com/markrendle/Simple.Data) to do this really easily. Because it uses C# dynamics, you can just load the dynamic type, and insert it directly into a second Simple.Data connection without worrying about type conversion.
Something like:
var db = Database.OpenConnection("data source=.;initial catalog=Xyz;etc");
var db2 = Database.OpenConnection("data source=somewhereElse;initial catalog=Xyz;etc");
dynamic user = db.Users.FindById(1);
db2.Users.Insert(user);
It works perfectly... I modified this code... Use it...
string local = "Server=destinationservername;Database=destinationserverdb;Uid=sa;Pwd=<Password>;
string dev = "Server=sourceservername;Database=sourceserverdb;Uid=sa;Pwd=Password;
private void btncopy_Click(object sender, EventArgs e)
{
CopyDatabaseRows(dev, local, query);
}
static public void CopyDatabaseRows(string ConnectionStringDEV, string ConnectionStringLOCAL, string queryString)
{
//Connect to first database table to retreive row/rows and populate dataset + datatable.
DataSet dataSet = new DataSet();
SqlConnection conn = new SqlConnection(ConnectionStringDEV);
conn.Open();
SqlCommand command = new SqlCommand(queryString, conn);
DataTable dataTable = new DataTable();
SqlDataAdapter dataAdapter = new SqlDataAdapter(queryString, conn);
dataAdapter.FillSchema(dataSet, SchemaType.Mapped);
dataAdapter.Fill(dataSet, "dbo.DeviceLogs");
dataTable = dataSet.Tables["dbo.DeviceLogs"];
conn.Close();
//Connect to second Database and Insert row/rows.
SqlConnection conn2 = new SqlConnection(ConnectionStringLOCAL);
conn2.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn2);
bulkCopy.DestinationTableName = "dbo.DeviceLogs";
bulkCopy.WriteToServer(dataTable);
MessageBox.Show(dataTable.Rows.Count.ToString() + " rows copied successfully", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}