I do the following:
SqlConnection conn = new SqlConnection("... my connection string ...");
dataAdapter = new SqlDataAdapter();
SqlCommand selectCommand = new SqlCommand("select * from items", conn);
dataAdapter.SelectCommand = selectCommand;
DataTable schemaTable = new DataTable();
dataAdapter.FillSchema(schemaTable, SchemaType.Source);
However, there are no rows in the schemaTable. dataAdapter.Fill() work.
I think you misunderstand what FillSchema does.
It takes the DataTable passed in (with no row and no column) and builds the schema adding the columns with infos about size, type etc... corresponding to the table that will be returned by the SelectCommand.
It doesn't fill the passed in table with records.
Infact, if you look at the Columns count after the call to FillSchema you will find that your schemaTable has been 'built' with columns matching the items table.
So, what is the use for a FillSchema call considering that a Fill call, equally fills the table with its columns names and types? Well, FillSchema is used to prepare the table passed in for the following Fill with some properties that otherwise are not loaded by the Fill call. For example, suppose that your items table has an AutoIncrement column. This property is not available on the the matching DataColumn after the call to Fill. But, if you pass to Fill, the table prepared by FillSchema, that property is available.
If you want just the infos about the columns of your table you need a different approach
using(SqlConnection con = new SqlConnection(.......)
{
con.Open();
DataTable schema = con.GetSchema("Columns", new string[] {null, null, "items"});
foreach(DataRow row in schema.Rows)
Console.WriteLine("TABLE:" + row.Field<string>("TABLE_NAME") +
" COLUMN:" + row.Field<string>("COLUMN_NAME"));
}
or in a more standard way
using(SqlConnection con = new SqlConnection(.......)
{
con.Open();
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='items'
AND TABLE_CATALOG = 'yourDBNameHere'", con);
SqlDataReader reader = cmd.ExecuteReader();
dt.Load(reader);
foreach(DataRow row in dt.Rows)
..... catalog, name, ordinal_position, column_default etc....
}
The FillSchema method retrieves the schema from the database using the SelectCommand. A FillSchema creates a DataTable with the PrimaryKey and Constraints properties, adds the columns to the DataColumnCollection and configures the necessary DataColumn properties. This method doesn't fill the datatable with rows, it only applies the schema. use the Fillmethod to do this.
Related
I'm using SQL 2014, Visual Studio 2013. I have the following code that's part of a larger script task:
//Load DataTable1 with Source Excel Sheet Data
OleDbCommand oconn = new OleDbCommand("select * from [" + sheetname + "]", cnn);
OleDbDataAdapter adp = new OleDbDataAdapter(oconn);
DataTable dt = new DataTable();
adp.Fill(dt);
What I would like to do next is select a targeted number of columns from datatable1, and fill another datatable. Something like this:
//Load another DataTable with Data from datatable1
OleDbCommand oconn2 = new OleDbCommand("select [column1], [column2] from datatable1", cnn);
OleDbDataAdapter adp2 = new OleDbDataAdapter(oconn2);
DataTable dt2 = new DataTable();
adp2.Fill(dt2);
Is this possible? The reason behind this is complicated, but I don't know another way around it. My source files are Excel. So the data needs to be brought into a datatable. Then the column names need to modified. Then a table can be made with the modified column names. But first, the data needs to be brought into a datatable as is, as I'm not sure I want to modify the source files.
Thank you.
Define the second DataTable using the data types and new names for the columns that will be added to it. Then you can populate this object by using the ordinal position of the columns in the initial DataTable with the Add method as below.
DataTable dt2 = new DataTable();
dt2.Columns.Add("NewColumnName1", typeof(int));
dt2.Columns.Add("NewColumnName2", typeof(string));
//in this example dt is the original DataTable
foreach (DataRow dr in dt.Rows)
{
//add only necessary columns by their
//ordinal position in source DataTable
dt2.Rows.Add(dr[1], dr[0]);
}
DataRow dr;
dr = ((dgv.DataSource) as DataTable).Rows[dgv.CurrentRow.Index];
dgv is DataGridView predefined on winform.
dr is single always.
Above code was found.
But it doesn't work right. Because CurrentRow.Index is not macthed to DataTable's Index.
I think to copy DataGridViewRow to DataRow is simplest way. Is it impossible?
Reason trying this is for Update to/Delete from database when dgv is changed. Any other better solution for remote DB CRUD from local dgv should be great.
Thanks in advance.
You can link you datagridview directly to your database table without passing by the datatable by defining an ID column in the database table (you can either display or not the ID column in the datagridview) as shown bellow
Code behind:
SqlCommand update = new SqlCommand();
update.connection = conn; // conn is your SqlConnection to the server
update.parameters.add("#Id",[sqldbtype.int]).value=dgv.Rows[dgv.CurrentRow.Index].Cell[0]; // 0 is the cell index of the ID column
update.Commandtext="Delete from table where [ID]=#ID" // delete the selected row
conn.open();
update.ExecuteNonQuery();
SqlDataAdapter adapter = SqlDataAdapter("SELECT*FROM Table", conn);
conn.close();
Datatable table = new Datatable();
adapter.Fill(table);
dgv.Datasource = table.Items;
i want to create a for loop in which i want to write a query which updates the the value of each row in database. the rows are present in the datagridview as well as in the database. the aim is when the changes are made in datagridview so using a button the change are also applied in the database table too. in each row the barcode and its quantity is different. if the changes are made in all the rows in datagridview so it is also to be applied in database using button and also please help with the parameters.
here is the query which should be considered in the for loop:
SqlCommand cmd2 = new SqlCommand("update prod_info set item_quantity=#qty where barcode=#barcode ", con);
consider barcode as column1 and item_quantity as column2.
so far to create a for loop i have tried this but getting error in the for loops:
for (int i = 0; dataGridView2.Rows.Count; i++) //getting error here
{
SqlCommand cmd2 = new SqlCommand("update prod_info set item_quantity=#qty where barcode=#barcode ", con);
cmd2.Parameters.AddWithValue("#barcode", dataGridView2.Rows[i].Cells[1].Value.ToString());
cmd2.Parameters.AddWithValue("#qty", dataGridView2.Rows[i].Cells[1].Value.ToString());
}
you should call cmd2.ExecuteNonQuery(); in your loop ... otherwise no sql commands will be executed
to get a better solution you should move to creation of cmd2 before the loop. also add the parameters there (without assigning values) ... inside the loop just assign the values and call ExecuteNonQuery.
maybe the best solution would be to use databinding and a SqlDataAdapter with assigned UpdateCommand.
just saw that there probably is an error in your code ... you use the value from Cell[1] for both of your parameters ...
example:
first create a DataTable ... var dt = new DataTable();
then add the columns you want in your grid to the DataTable ... dt.Columns.Add("xyz");
then attach the DataTable to your grid: dataGridView2.DataSource = dt;
now you should be able to edit the contents of column "xyz". to write the values to the database you create a SqlDataAdapter ... var adp = new SqlDataAdapter();
then set adp.InsertCommand = new SqlCommand(...) and adp.UpdateCommand = new SqlCommand(...)
now you can call adp.Update(); and all the values from your grid are written to db ... for newly added rows the InsertCommand is invoked and for edited rows the UpdateCommand is invoked.
I created an Excel application using C# with MVVM model. In that excel file I created some columns as template columns. For example I am having some columns like Unit, Cost and Quantity. Now I want to find the exact column number of "Quantity" .
How can I get that particular column(Quantity) number?
Please can any one tell me some method to achieve this?
Execute the Select statement and fill the dataset. Now traverse through the column in the table and find the index of column 'Quantity".
Sample code to load the excel file in Dataset:
public static DataSet exceldata(string filelocation)
{
DataSet ds = new DataSet();
OleDbCommand excelCommand = new OleDbCommand(); OleDbDataAdapter excelDataAdapter = new OleDbDataAdapter();
string excelConnStr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + filelocation + "; Extended Properties =Excel 8.0;Hdr=Yes";
OleDbConnection excelConn = new OleDbConnection(excelConnStr);
excelConn.Open();
DataTable dtPatterns = new DataTable(); excelCommand = new OleDbCommand("SELECT `PATTERN` as PATTERN, `PLAN` as PLAN FROM [PATTERNS$] where 1=0", excelConn);
excelDataAdapter.SelectCommand = excelCommand;
excelDataAdapter.Fill(dtPatterns);
"dtPatterns.TableName = Patterns";
ds.Tables.Add(dtPatterns);
return ds;
}
By using this method, you have loaded the table schema in dataset. Now you can store the column name and index in any of the collection variable and get the column index using the key column name in that collection.
I've got an assignment which requires me to update the northwind database,
I've done everything like the tutorials say as follows
I fill The DataTable Using The DataAdapter.Fill(table).
I build the Delete,Insert,Update Commands using CommangBuilder
SqlDataAdapter adapter = new SqlDataAdapter(selectStr, conn);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.DeleteCommand = builder.GetDeleteCommand(true);
adapter.UpdateCommand = builder.GetUpdateCommand(true);
adapter.InsertCommand = builder.GetInsertCommand(true);
adapter.Fill(employees_table);
I also set a primary key for the table:
DataColumn[] employees_keys = new DataColumn[2];
employees_keys[0] = employees.Columns["EmployeeID"];
employees_table.PrimaryKey = employees_keys;
Now I've attempted to delete and add a row:
// accepts an employee object and creates a new new row with the appropriate values for
// an employee table row
DataRow row = ConvertEmployeeToRow(employeeToAdd);
employee_table.Rows.Add(row);`
and deleting a row:
DataRow row = employees.Rows.Find(employeeToDismiss.ID);
employees.Rows.Remove(row);
I should also point out that I've attempted to use row.SetAdded() and row.Delete()
Anyway, at the end when I try to update the database
int k = employees_adapter.Update(employees_table);
on added rows sometimes k get valued, on remove never, and in either case nothing really gets updated at all in the database itself.
Any insight of what I'm doing wrong?
Make sure you're calling employee_table.AcceptChanges() after the call to Update() to save the changes to the database.
Check if the CommandBuilder really makes an Update command for you, like this:
MessageBox.Show(adapter.UpdateCommand.CommandText);
If the primary key info is missing it won't build the update command at all!
I am little confuse here your SqlDataAdapter name is adapter and you are doing updation in employees_adapter.The steps are so simple to work with SqlDataAdapter just follow theses
Step No 1:
SqlDataAdapter adapter = new SqlDataAdapter(selectStr, conn);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
DataTable employees_table= new DataTable ();
adapter.Fill(employees_table);
Step No 2:
After you got the data in dataset start manipulation on it..
To insert :
DataRow MyRow = employees_table.NewRow();
//Now Fill data in MyRow
employees_table.Tables[0].Rows.Add(MyRow);
employees_table.AcceptChanges();
adapter.Update(employees_table);
To Delete :
/get only the rows you want
DataRow[] result = employees_table.Select("ID ="+id); //id will be provided by you
//Now do here data updation
employees_table.AcceptChanges()
adapter.Update(employees_table);
Like wise you can apply updation..But after doing any changes must call
table.AcceptChanges() and then'adapter.Update(employees_table)'