ADO.NET - Updating Multiple DataTables - c#

So I have some code like this:
DataSet dataSet = new DataSet();
DataTable dataTable1 = new DataTable("Table1");
DataTable dataTable2 = new DataTable("Table2");
DataTable dataTable3 = new DataTable("Table3");
DataTable dataTable4 = new DataTable("Table4");
dataSet.Tables.Add(dataTable1);
dataSet.Tables.Add(dataTable2);
dataSet.Tables.Add(dataTable3);
dataSet.Tables.Add(dataTable4);
SqlDataAdapter dataAdapter1 = new SqlDataAdapter("SELECT * FROM Table1 WHERE ID = 1", sqlConnection);
SqlDataAdapter dataAdapter2 = new SqlDataAdapter("SELECT Column1, Column2, Column3 FROM Table2", sqlConnection);
SqlDataAdapter dataAdapter3 = new SqlDataAdapter("SELECT Column1, Column2, Column3 FROM Table3", sqlConnection);
SqlDataAdapter dataAdapter4 = new SqlDataAdapter("SELECT Column1, Column2, Column3 FROM Table4", sqlConnection);
SqlCommandBuilder commandBuilder1 = new SqlCommandBuilder(dataAdapter1);
SqlCommandBuilder commandBuilder2 = new SqlCommandBuilder(dataAdapter2);
SqlCommandBuilder commandBuilder3 = new SqlCommandBuilder(dataAdapter3);
SqlCommandBuilder commandBuilder4 = new SqlCommandBuilder(dataAdapter4);
dataAdapter1.Fill(dataTable1);
dataAdapter2.FillSchema(dataTable2, SchemaType.Source);
dataAdapter3.FillSchema(dataTable3, SchemaType.Source);
dataAdapter4.FillSchema(dataTable4, SchemaType.Source);
//do a bunch of code that updates the one row from Table1
//and adds lots of new rows to Table2, Table3, Table4
dataAdapter1.Update(dataTable1);
dataAdapter2.Update(dataTable2);
dataAdapter3.Update(dataTable3);
dataAdapter4.Update(dataTable4);
dataSet.AcceptChanges();
Is there anyway to make this a lot simpler? What would happen if the computer crashed on the line after "dataAdapter2.Update(dataTable2);"? I would like to be able to somehow use just one Update call to update everything. Is that possible?
Also, is this even the best way to do this? With "this" being creating a bunch of new rows in multiple tables depending on what is in one specific row in one specific table.

You can pass a dataset into a DataAdapter's Update statement, which will update all of the tables in the dataset. UPDATE: No, it doesn't. DataAdapters always update only one table. The overload to Update() that takes a DataSet as its parameter, from the MSDN documentation, "Calls the respective INSERT, UPDATE, or DELETE statements for each inserted, updated, or deleted row in the specified DataSet from a DataTable named "Table"." Sorry for the confusion. The rest of the answer is still valid, though.
If you want to assure that all the updates succeed or fail as an atomic unit, use the SqlTransaction object:
DataSet ds = new DataSet();
// do something with the dataset
SqlDataAdapter dataAdapter = new SqlDataAdapter();
SqlConnection cn = new SqlConnection(connString);
cn.Open();
SqlTransaction trans = cn.BeginTransaction();
SqlDataAdapter dataAdapter = new SqlDataAdapter();
// set the InsertCommand, UpdateCommand, and DeleteCommand for the data adapter
dataAdapter.InsertCommand.Transaction = trans;
dataAdapter.UpdateCommand.Transaction = trans;
dataAdapter.DeleteCommand.Transaction = trans;
try
{
dataAdapter.Update( ds );
trans.Commit();
}
catch
{
trans.Rollback();
}
cn.Close();

Related

How to add a column when using SqlDataAdapter to fill a datagridview

I am using SQL to fill my datagridview. I am doing that this way:
string cn = ConfigurationManager.ConnectionStrings["Scratchpad"].ConnectionString;
SqlConnection myConnection = new SqlConnection(cn);
string sql = "some text here";
SqlDataAdapter dataadapter = new SqlDataAdapter(sql, myConnection);
DataSet ds = new DataSet();
myConnection.Open();
dataadapter.Fill(ds, "Authors_table");
myConnection.Close();
dataGridView1.DataSource = ds;
dataGridView1.DataMember = "Authors_table";
Now it deletes the old datagridview and paste the selection. But I want just to add the data to the column right of the existing data.
Thanks in advance
This requirement sounds like it could be met with a SQL Inner Join in the query you're using in your SqlDataAdapter. If you were able to join your two data sources together on matching keys, you could simply pull the data down once. But I'm going to assume there's some reason why that won't work for you.
You can in fact do what you want with a DataSet, but you'll need to take a few more steps:
string sql = "The first query"
SqlDataAdapter dataadapter = new SqlDataAdapter(sql, myConnection);
DataSet ds = new DataSet();
myConnection.Open();
dataadapter.Fill(ds, "Authors_table");
myConnection.Close();
// I don't know what your primary key is, but you need to have one.
// I am assuming it's called "author_id".
DataColumn authorIdColumn = ds.Tables["Authors_table"].Columns["author_id"];
ds.Tables["Authors_table"].PrimaryKey = new[] { authorIdColumn };
// Get your second set of data
sql = "My second query, which also has the same primary key, but has more columns"
dataadapter = new SqlDataAdapter(sql, myConnection);
dataadapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
DataSet ds2 = ds.Clone();
myConnection.Open();
dataadapter.Fill(ds2, "Authors_table");
myConnection.Close();
// Now we use the DataSet.Merge method, which is very powerful.
ds.Merge(ds2, false, MissingSchemaAction.AddWithKey);
dataGridView1.DataSource = ds;
dataGridView1.DataMember = "Authors_table";
You may have to experiment with that a lot: this is just the outline. Without knowing your data and what you do up to this point, it's hard to know what settings or methods you might also need to call.
Try this. I ran multiple queries in one go
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT * FROM Customers; SELECT * FROM Orders", connection);
adapter.TableMappings.Add("Table", "Customer");
adapter.TableMappings.Add("Table1", "Order");
adapter.Fill(ds);

Dataset filter method

Here is my code,
Conn.Open();
DataTable dt = new DataTable();
DataSet ds = new DataSet();
SqlCommand sqlCmd = new SqlCommand("SELECT * from CurrentDataCR ",Conn);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
sqlDa.Fill(ds);
ds.Tables[0].DefaultView.RowFilter = " mst_remote_station_id Like'*9001*'";
Here I am getting Complete row for id 9001. I need only one column value for this id.
DataRow[] rows = ds.Tables[0].Select("mst_remote_station_id Like '%9001%'");
You can do it this way also if you need only one row just select it in the initial query.
Also you should Dispose the SqlDataAdapter after using it ! You can do it with using block
Conn.Open();
DataSet ds = new DataSet();
SqlCommand sqlCmd = new SqlCommand("SELECT * from CurrentDataCR ",Conn);
using(SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd))
{
sqlDa.Fill(ds);
}
ds.Tables[0].Select("mst_remote_station_id Like '%9001%'");
I don't know if the connection is global but it is bad practice to use global connection, you have connection pool so use separate connection for every query.

Read data from a database in C#

I have created a table name glossary in a database named ChatBotDataBase in SQL Server. I want to read the data in a special column of the table.
To do so, I have written this code:
private void button1_Click(object sender, EventArgs e)
{
SqlConnection sc = new SqlConnection();
sc.ConnectionString = #"Data Source=shirin;Initial Catalog=ChatBotDataBase;
Integrated Security=True";
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = new SqlCommand();
sda.SelectCommand.Connection = sc;
sda.SelectCommand.CommandText = "SELECT * FROM glossary";
DataTable table = new DataTable();
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
}
But there is an error in last line.
The error is :
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in System.Data.dll.
And here is a print screen of the mentioned table:
Can anyone help please?
Looks like you are confusing the Datatable called table with your database table in your sql server. In your image you show us the glossary table in your sql server, not the DataTable called table.
You get this error because you create an empty DataTable called table with DataTable table = new DataTable() but you didn't even fill your table. That's why it doesn't have any rows by default.
SqlCommand cmd = new SqlCommand("SELECT * FROM glossary");
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sda.Fill(table);
Also use using statement to dispose your SqlConnection, SqlCommand and SqlDataAdapter.
using(SqlConnection sc = new SqlConnection(conString))
using(SqlCommand cmd = sc.CreateCommand())
{
cmd.CommandText = "SELECT * FROM glossary";
...
using(SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
DataTable table = new DataTable();
sda.Fill(table);
if(dt.Rows.Count > 0)
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
}
}
Below code will help you
sda.SelectCommand.CommandText = "SELECT * FROM glossary";
DataTable table = new DataTable();
sda.Fill(table , "glossary");
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
You haven't executed the query or populated the table. It is empty. It has no columns and no rows. Hence the error.
Frankly, though, I strongly suggest using a typed class model, not any kind of DataTable. With tools like "dapper", this can be as simple as:
var list = conn.Query<Glossary>("SELECT * FROM glossary").ToList();
With
public class Glossary {
public int Id {get;set}
public string String1 {get;set} // horrible name!
....
public int NumberOfUse {get;set}
}
Dear kindly first fill your table with the data.
And you should use checks because if there is no data then you get a proper message.check is below..
if(dt.Rows.Count > 0)
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
else if(dt.Rows.Count > 0)
MessageBox.Show("Table is empty");
And other advice is that you should display data into DataGrid.... Displaying data from Database into a message box is not a good programming approach..
For displaying DataTable into DataGrid in C# is as simple as below.
SqlCommand cmd = new SqlCommand("select * from student",con);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
DataTable dt = new DataTable();
dt.TableName = "students";
da.Fill(dt);
dataGridView1.DataSource =dt;
using System.Data.Odbc;
OdbcConnection con = new OdbcConnection("<connectionstring>");
OdbcCommand com = new OdbcCommand("select * from TableX",con);
OdbcDataAdapter da = new OdbcDataAdapter(com);
DataSet ds = new DataSet();
da.Fill(ds,"New");
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables["New"];
you can get the connection string from:
http://www.connectionstrings.com/

SqlAdapter.Update() method perform insertion instead of updation

I used SqlAdapter.Update() method to update the rows in a table.
For that I created Datatable and add values to that datatable.
DataTable dtTable = new DataTable("Product");
SqlConnection myLocalConnection = new SqlConnection(_ConnectionString);
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter("Select * from " + dtTable.TableName, myLocalConnection);
SqlCommandBuilder mySqlCommandBuilder = new SqlCommandBuilder(mySqlDataAdapter);
mySqlDataAdapter.Update(dtTable);
When I using this command it insert new rows in the database rather than updating the existing rows. Why does this happen?
I think what is happening here is (As per your given code) your dataadapter is unable to recognize rows in your datatable it is nowhere related to your datatable here, So as a guess try to fill your datatable via dataadapter then modify your datatable and update it.
DataTable dtTable = new DataTable();
SqlConnection myLocalConnection = new SqlConnection(_ConnectionString);
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter("Select * from " +
dtTable.TableName, myLocalConnection);
SqlCommandBuilder builder= new SqlCommandBuilder(mySqlDataAdapter);
mySqlDataAdapter.Fill(dtTable,"Products" )
// Code to modify your datatable
mySqlDataAdapter.UpdateCommand = builder.GetUpdateCommand();
mySqlDataAdapter.Update(dtTable);
-- Hope it helps .
This is just an idea and not the solution...
// update command to update database table.
string strUpdateCommand =
"Update Students set Name = #Name, Gender = #Gender, Total = #Total where ID = #ID";
// create an instance of SqlCommand using the update command created above.
SqlCommand updateCommand = new SqlCommand(strUpdateCommand, con);
// specify the paramaters of the update command.
updateCommand.Parameters.Add("#Name", SqlDbType.NVarChar, 50, "Name");
updateCommand.Parameters.Add("#Gender", SqlDbType.NVarChar, 20, "Gender");
updateCommand.Parameters.Add("#Total", SqlDbType.Int, 0, "Total");
updateCommand.Parameters.Add("#ID", SqlDbType.Int, 0, "ID");
// associate update command with SqlDataAdapter instance.
dataAdapter.UpdateCommand = updateCommand;

Checking if column allows null values, C#?

How do I check if a specified column allows null values or not?
I'm using the following code to print all the columns, but I also want to print if the column allows null values:
cnn = new SqlConnection(connetionString);
cnn.Open();
SqlCommand myCommand = new SqlCommand("select * from " + tableName, cnn);
SqlDataAdapter da = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
da.Fill(ds, tableName);
foreach (DataColumn dc in ds.Tables[0].Columns)
{
// Print stuff here, dc.ColumnName is the column name
}
The DataColumn.allowDBnull property doesn't seem to work when getting a predefined table, it's always set to true, even in columns that doesn't allow nulls.
Thanks for your time!
If you are only after column data I would do this from the system views, rather than relying on the data adapter. e.g.
DECLARE #TableName VARCHAR(50) = 'dbo.TableName'
SELECT Name, Column_ID, Is_Nullable
FROM SYS.COLUMNS
WHERE [Object_ID] = OBJECT_ID(#TableName)
This also means you can use parameterised queries properly and avoid the risks of SQL Injection. So your final code would be something like this:
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand("SELECT Name, Is_Nullable FROM sys.columns WHERE [Object_ID] = OBJECT_ID(#TableName)", connection))
{
connection.Open();
command.Parameters.Add("#TableName", SqlDbType.VarChar).Value = tableName;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("Name: {0}; Allows Null: {1}", reader.GetString(0), reader.GetBoolean(1));
}
}
}
SqlDataAdapter.Fill() Adds or refreshes rows and does nothing in relation to a table schema information which knows whether particular column allows null. But you can use SqlDataAdapter.FillSchema() to load schema information, then AllowsDBNull would show you a correct state of a column.
SqlDataAdapter da = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
da.FillSchema(ds, SchemaType.Source, tableName);
da.Fill(ds, tableName);
da.FillSchema(ds, SchemaType.Source, tableName);//Loads all the constraints and relations of tables
da.Fill(ds, tableName);//Loads the data
cnn = new SqlConnection(connetionString);
cnn.Open();
SqlCommand myCommand = new SqlCommand("
select name,is_nullable from sys.columns where object_id=object_id('"+tableName+"')", cnn);
SqlDataAdapter da = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
da.Fill(ds, tableName);
foreach (datarow in ds.Tables[0].rows)
{
if(dr["is_nullable"].ToString()==1)
//the column is nullable
else
//column is not nullable
}

Categories

Resources