Cannot add DataTable into MS Access table - c#

I have a DataTable with about 6000 rows created from a query to SQL Server DB. Now I try to add the data into a MS-Access table. Everything seems to work. No exceptions are raised but no data is a being added. Here is the code I'm using:
DataTable t = new DataTable();
// fill data table
// Create DB - works!
var Name = DateTime.Now.ToString("H_mm_ss");
string strAccessConnectionString = #"Provider = Microsoft.Jet.OLEDB.4.0;" +
#"Data Source=" + "C:\\chhenning\\" + Name + ".mdb;";
ADOX.CatalogClass Catalog = new ADOX.CatalogClass();
Catalog.Create(strAccessConnectionString);
OleDbConnection accessConnection = new OleDbConnection(strAccessConnectionString);
accessConnection.Open();
// Create Table - works!
OleDbCommand Command = accessConnection.CreateCommand();
Command.CommandText = "Create Table Test( "
+ " ID_ int not null "
+ " , Year_ int not null "
+ " , Value_ float not null )";
Command.ExecuteNonQuery();
// Add data into table - does not work!
var adapter = new OleDbDataAdapter();
adapter.SelectCommand = new OleDbCommand("select * from Test", accessConnection);
var cbr = new OleDbCommandBuilder(adapter);
cbr.GetInsertCommand();
var Rows = adapter.Update(t);
I have made sure that my DataTable has data in and that both the DataTable and MS-Access have the same columns with the same data types.
Can someone spot what wrong with code? What are the steps I do to investigate the problem further?

The adapter.Update(table) method works looking at the RowState of the rows in the DataTable.
If the rows have RowState == DataRowState.Unchanged, the method will not perform any update.
I suppose that you load the datatable from the SqlServer database without making any change and thus the RowState is Unchanged for every row. Try to loop on the Rows and call
foreach(DataRow r in t.Rows)
r.SetAdded();
This will force the RowState on each column to Added and then the InsertCommand on the DataAdapter will execute the insert

Related

How do I display a select from database consisting of multiple join in a text box?

I have to do a select from database that have multiple join( i will show you belong) and i put in one command . The problem it is next one : a select something from a table and when i run the code it tell me something like that : " Column '....' does not belong to table ." and i look into table and it is. I will put code for take a look. Do you have any idea? I am sure i do something wrong but i don t know what.
string connectionString = "Data Source=..." +
"User=..." +
"Password=..";
OracleConnection con = new OracleConnection();
con.ConnectionString = connectionString;
con.Open();
string select3 = "SELECT tblOwner.OwnerFirstName , tblOwner.OwnerLastName, tblOwner.OwnerEmailID, tblOwner.OwnerLoc, tblDomain.DomainName " +
" FROM tblDomain " +
" INNER JOIN(tblOwner INNER JOIN tblProductInfo ON tblOwner.OwnerID = tblProductInfo.OwnerID) ON tblDomain.DomainIDShort = tblOwner.DomainID" +
" WHERE(((tblProductInfo.Productname) = ' "+ mystring +
"'" + "))";
OracleDataAdapter aa = new OracleDataAdapter(select3, con);
DataTable cc = new DataTable();
bb.Fill(cc);
foreach (DataRow ww in dt.Rows)
{
textBox2.Text = (ww["DomainName"].ToString());
}
Your DataTable seems to not have a column called "DomainName". You can use the following code to list the existing column names in the output window of visual studio.
foreach (DataColumn col in cc.Columns)
{
Debug.WriteLine(col.ColumnName);
}
First: You are filling DataTable from different data adapter.
OracleDataAdapter aa = new OracleDataAdapter(select3, con); // aa created
DataTable cc = new DataTable();
bb.Fill(cc); // 'bb' fills data
Second: You are reading data from different DataTable, not that which you are filling with data.
DataTable cc = new DataTable();
bb.Fill(cc); // 'cc' variable filled with data
foreach (DataRow ww in dt.Rows) // reading rows from 'dt' variable
{
textBox2.Text = (ww["DomainName"].ToString());
}

Get AutoNumber column index in Ms Access 2010/2013

(first sorry for my English):
I want to temporarily change auto-number column to int64 data type to import records from another database. After importing the records, I want to change it back to auto-number.
My Problem:
I try to use the table.Columns[i].AutoIncrement property to check if this column is auto-number and get its index so that I can change its datatype, but this property didn't work for me, it returned false for all columns.
I work with 2010/2013 Access database.
So I want to know what to do to get index of auto-number column?
You can use this approach
// Bogus query, we don't want any record, so add a always false condition
OleDbCommand cmd = new OleDbCommand("SELECT * FROM aTable where 1=2", con);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataTable test = new DataTable();
da.FillSchema(test, SchemaType.Source);
for(int x = 0; x < test.Columns.Count; x++)
{
DataColumn dc = test.Columns[x];
Console.WriteLine("ColName = " + dc.ColumnName +
", at index " + x +
" IsAutoIncrement:" + dc.AutoIncrement);
}

Error with SqlDataAdapter Update

Using C#, SQL Server 2016 - Trying to write a method to update every record in a dataset - a single field to a new value - using a DataAdapter object, and am getting the following error message:
Dynamic SQL generation is not supported against a SelectCommand that does not return any base table information.
Here is my code (a method on a class containing a DataSet TheDS, an SQLDataAdapter TheAdapter, and a DataTable TheDataTable):
public void updateDSField<T>(string fieldName, T newVal)
{
// Updates field in dataset
SqlCommandBuilder builder = new SqlCommandBuilder(TheAdapter);
var col = TheDataTable.Columns[fieldName];
foreach (DataRow row in TheDataTable.Rows) row[col] = newVal;
TheAdapter.UpdateCommand = builder.GetUpdateCommand();
TheAdapter.Update(TheDS);
}
I read something about the SqlCommandBuilder not being able to handle >1000 rows - is that correct? Either way, what is the correct way to perform this operation?
I needed to build my own command string, as the builder does not handle more than 1000 rows. I was worried that this would update the entire table at first, but this link
C# DataTable Update Multiple Lines
put my mind at ease. (Assuming also I know the table name, TheTableName).
public void updateDSField<T>(string fieldName, T newVal)
{
// updates field in dataset
var col = TheDataTable.Columns[fieldName];
foreach (DataRow row in TheDataTable.Rows) row[col] = newVal; // * this marks the rows to be update by the commandtext
// create adapter and update string
TheAdapter.UpdateCommand = TheConn.CreateCommand();
string newValString = newVal.ToString();
if (typeof(T) == typeof(string)) newValString = "'" + newValString + "'";
TheAdapter.UpdateCommand.CommandText = "UPDATE [" + TheTableName + "] SET [" + fieldName + "] =" + newValString;
TheAdapter.Update(TheDS); // this will only update those rows marked by step * above
}

Finding unique rows in SQL Server Table

I'm looking at the example here:
http://msdn.microsoft.com/en-US/library/y06xa2h1(v=vs.80).aspx
string s = "primaryKeyValue";
DataRow foundRow = dataSet1.Tables["AnyTable"].Rows.Find(s);
if (foundRow != null)
{
MessageBox.Show(foundRow[1].ToString());
}
else
{
MessageBox.Show("A row with the primary key of " + s + " could not be found");
}
They don't specify where does dataSet1 come from and does this represent some database?
I'm trying to use this example in my code to find unique rows but I can't seem to implement this syntax. I'm only using connection string to open connection to SQL and I use SqlDataAdapter to perform functions...
EDIT:
SqlConnection myConnection = new SqlConnection("Data Source=server; Initial Catalog=Dashboard; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
try
{
//Opens the connection to the specified database
myConnection.Open();
//Specifies where the Table in the database where the data will be entered and the columns used
da.InsertCommand = new SqlCommand("INSERT INTO DashboardLibAnswer(Id,Date,Time,Question,Details,Answer,Notes,EnteredBy,WhereReceived,QuestionType,AnswerMethod,TransactionDuration)"
+ "VALUES(#Id,#Date,#Time,#Question,#Details,#Answer,#Notes,#EnteredBy,#WhereReceived,#QuestionType,#AnswerMethod,#TransactionDuration)", myConnection);
//Specifies the columns and their variable type where the data will be entered
//Special note: Conversion from String > DateTime will cause exceptions that will only import some part of data and not everything
da.InsertCommand.Parameters.Add("#Id", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#Date", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Time", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Question", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Details", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Answer", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Notes", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#EnteredBy", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#WhereReceived", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#QuestionType", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#AnswerMethod", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#TransactionDuration", SqlDbType.NVarChar);
//Using the global variable counter this loop will go through each valid entry and insert it into the specifed database/table
for (int i = 0; i < counter; i++)
{
//Iterates through the collection array starting at first index and going through until the end
//and inserting each element into our SQL Table
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "DashboardLibAnswer");
DataTable dt = dashboardDS.Tables["DashboardLibAnswer"];
foreach (DataColumn col in dt.Columns)
{
if (col.Unique)
{
da.InsertCommand.Parameters["#Id"].Value = collection.getIdItems(i);
da.InsertCommand.Parameters["#Date"].Value = collection.getDateItems(i);
da.InsertCommand.Parameters["#Time"].Value = collection.getTimeItems(i);
da.InsertCommand.Parameters["#Question"].Value = collection.getQuestionItems(i);
da.InsertCommand.Parameters["#Details"].Value = collection.getDetailsItems(i);
da.InsertCommand.Parameters["#Answer"].Value = collection.getAnswerItems(i);
da.InsertCommand.Parameters["#Notes"].Value = collection.getNotesItems(i);
da.InsertCommand.Parameters["#EnteredBy"].Value = collection.getEnteredByItems(i);
da.InsertCommand.Parameters["#WhereReceived"].Value = collection.getWhereItems(i);
da.InsertCommand.Parameters["#QuestionType"].Value = collection.getQuestionTypeItems(i);
da.InsertCommand.Parameters["#AnswerMethod"].Value = collection.getAnswerMethodItems(i);
da.InsertCommand.Parameters["#TransactionDuration"].Value = collection.getTransactionItems(i);
da.InsertCommand.ExecuteNonQuery();
}
}
//Updates the progress bar using the i in addition to 1
_worker.ReportProgress(i + 1);
} // end for
//Once the importing is done it will show the appropriate message
MessageBox.Show("Finished Importing");
} // end try
catch (Exception exceptionError)
{
//To show exceptions thrown just uncomment bellow line
//rtbOutput.AppendText(exceptionError.ToString);
} // end catch
//Closes the SQL connection after importing is done
myConnection.Close();
}
if you populate a dataset from your data adapter, you'll be able to follow the same logic -
http://msdn.microsoft.com/en-us/library/bh8kx08z(v=vs.71).aspx
It might be worth showing what you actually have to get more specific help
EDIT
I think I'm understanding what you want - if you fill your datatable from the already populated table, just check the item doesn't already exist before adding it - i.e.
if (dt.Rows.Find(collection.getIdItems(i)) == null)
{
// add your new row
}
(just to be sure I knocked together a quick test - hopefully this helps):
// MyContacts db has a table Person with primary key (ID) - 3 rows - IDs 4,5,6
SqlConnection myConnection = new SqlConnection("Data Source=.; Initial Catalog=MyContacts; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand("select * from Person", myConnection);
myConnection.Open();
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "Person");
dashboardDS.Tables[0].PrimaryKey = new[] { dashboardDS.Tables[0].Columns["ID"]};
List<int> ids = new List<int> {4, 6, 7};
foreach (var id in ids)
{
if (dashboardDS.Tables[0].Rows.Find(id) == null)
{
Console.WriteLine("id not in database {0}", id); //i.e. 7
}
}
You will first need to open a connection to your database. This is an excellent source for connection strings: The Connection String Reference.
Then you will need to fill the dataset with data from some table. Since we are only interested in the schema information we are only selecting one row (SELECT TOP 1 ...).
Then we can go through the columns and check their Unique property (Boolean):
string connString =
"server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI";
string sql = #"SELECT TOP 1 * FROM AnyTable";
using (SqlConnection conn = new SqlConnection(connString)) {
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
using (DataSet ds = new DataSet()) {
da.Fill(ds, "AnyTable");
DataTable dt = ds.Tables["AnyTable"];
foreach (DataColumn col in dt.Columns) {
if (col.Unique) {
Console.WriteLine("Column {0} is unique.", col.ColumnName);
}
}
}
}
UPDATE #1
Sorry, I missunderstood your question. The above example returns unique columns, not unique rows. You can get unique (distinct) rows by using the DISTINCT keyword in SQL:
SELECT DISTINCT field1, field2, field3 FROM AnyTable
You can then fill the data table the same way as above.
Usually the word "unique" is used for unique constraints and unique indexes in database jargon. The term "distinct" is used for rows which are different.
UPDATE #2
Your updated question seems to suggest that you don't want find unique rows, but that you want to insert unique rows (which is the exact opposite).
Usually you would select distinct items from a collection like this. However it is difficult to answer your question accurately, since we don't know the type of your collection.
foreach (var item in collection.Distinct()) {
}
UPDATE #3
The easiest way to insert distinct values in the SQL Server table is to filter the rows at their origin, when reading them from the CSV-File; even before splitting them.
string[] lines = File.ReadAllLines(#"C:\Data\MyData.csv");
string[][] splittedLines = lines
.Distinct()
.Select(s => s.Split(','))
.ToArray();
Now you have distinct (unique) splitted lines that you can insert into the SQL Server table.

copy all rows of a table to another table

I have two databases in MySQL and SQL Server, and I want to create tables in SQL Server and copy all rows from the table in MySQL into the new table in SQL Server.
I can create table in SQL Server same as MySQL, with this code:
List<String> TableNames = new List<string>();
{
IDataReader reader=
ExecuteReader("SELECT Table_Name FROM information_schema.tables WHERE table_name LIKE 'mavara%'",MySql);
while (reader.Read()) {
TableNames.Add(reader[0].ToString());
}
reader.Close();
}
foreach (string TableName in TableNames) {
IDataReader reader =
ExecuteReader("SELECT Column_Name,IS_NULLABLE,DATA_TYPE FROM information_schema.columns where TABLE_Name='" + TableName + "'",MySql);
List<string[]> Columns = new List<string[]>();
while (reader.Read()) {
string[] column = new string[3];
column[0] = reader[0].ToString();
column[1] = reader[1].ToString();
column[2] = reader[2].ToString();
Columns.Add(column);
}
reader.Close();
// create table
string queryCreatTables= "CREATE TABLE [dbo].[" + TableName + "](\n";
foreach(string[] cols in Columns)
{
queryCreatTables +="["+ cols[0] + "] " + cols[2] + " ";
if (cols[1] == "NO")
queryCreatTables += "NOT NULL";
// else
// queryCreatTables += "NULL";
queryCreatTables += " ,\n ";
}
queryCreatTables += ")";
System.Data.SqlClient.SqlCommand smd =
new System.Data.SqlClient.SqlCommand(queryCreatTables, MsSql);
System.Data.SqlClient.SqlDataReader sreader = smd.ExecuteReader();
sreader.Close();
but I have problem to copy rows from one table into another table.
for select query, I use Idatareader, but I don't know how insert rows to another table.
For inserting rows from one table into another table please refer the below sample query
INSERT INTO Store_Information (store_name, Sales, Date)
SELECT store_name, sum(Sales), Date
FROM Sales_Information
The algorithm is as follows:
1. For each table in source database
2. Get a list of columns for that table
3. Create table in destination database
4. SELECT * FROM the table in source
5. For each row in data
6. Generate INSERT statement and execute on destination database
The information you need for a column is Name, Type, Length, etc.
Then you generate the insert statement by iterating on the columns
var insertStatement = "INSERT INTO " + tableName + " VALUES( ";
foreach( var column in columns )
insertStatement += "#" + column.Name + ",";
insertStatement[insertStatement.Length-1] = ')';
var command = new SqlCommand( insertStatement, MsSql );
// iterate over the columns again, but this time set values to the parameters
foreach( var column in columns )
command.Parameters.AddWithValue( "#"+column.Name, currentRow[column.Name] );
But I have a problem to copy rows from one table into another table.
You can use the SqlDataAdapter.UpdateBatchSize to perform Batch Updates/Inserts with a DataAdapter against the database to copy the data from one table to the other. After you get all records from the first MYSQL table using something like:
//Get the rows from the first mysql table as you did in your question
DataTable mysqlfirstTableRowsTobeCopied = GetDataTableFromMySQLTable();
Then you have to create a commend text that do the INSERT something like:
cmd.CommandText = "INSERT INTO TableName Column_Name, ... VALUES(...)";
Or you can use a stored procedure:
CREATE PROCEDURE sp_BatchInsert ( #ColumnName VARCHAR(20), ... )
AS
BEGIN
INSERT INTO TableName VALUES ( #ColumnNamne, ...);
END
Then:
DataTable mysqlfirstTableRowsTobeCopied = GetDataTableFromMySQLTable();
SqlConnection conn = new SqlConnection("Your connection String");
SqlCommand cmd = new SqlCommand("sp_BatchInsert", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.UpdatedRowSource = UpdateRowSource.None;
// Set the Parameter with appropriate Source Column Name
cmd.Parameters.Add("#ColumnName", SqlDbType.Varchar, 50,
mysqlfirstTableRowsTobeCopied.Columns[0].ColumnName);
...
SqlDataAdapter adpt = new SqlDataAdapter();
adpt.InsertCommand = cmd;
// Specify the number of records to be Inserted/Updated in one go. Default is 1.
adpt.UpdateBatchSize = 20;
conn.Open();
int recordsInserted = adpt.Update(mysqlfirstTableRowsTobeCopied);
conn.Close();
This code actually is quoted from a full tutorial about this subject in the codeproject, you can refer to it for more information:
Multiple Ways to do Multiple Inserts
Assuming that you already have a datatable with rows that you want to merge with another table...
There are two ways to do this...again, assuming you've already selected the data and put it into a new table.
oldTable.Load(newTable.CreateDataReader());
oldTable.Merge(newTable);
Usually that's sth. you can do in SQL directly: INSERT INTO table FROM SELECT * FROM othertable;
For insertion of all record into new table(If the second table is not exist)
Select * into New_Table_Name from Old_Table_Name;
For insertion of all records into Second Table(If second table is exist But the table structure should be same)
Insert into Second_Table_Name from(Select * from First_Table_Name);
Just in case it can help someone, I've found an easy way to do it in C# using SqlDataAdapter. It automatically detects the structure of the table so you don't have to enumerate all the columns or worry about table structure changing. Then bulk inserts the data in the destination table.
As long as the two tables have the same structure, this will work. (For example, copying from a production table to a dev empty table.)
using(SqlConnection sqlConn = new SqlConnection(connectionStringFromDatabase))
{
sqlConn.Open();
using(var adapter = new SqlDataAdapter(String.Format("SELECT * FROM [{0}].[{1}]", schemaName, tableName), sqlConn))
{
adapter.Fill(table);
};
}
using(SqlConnection sqlConn = new SqlConnection(connectionStringDestination))
{
sqlConn.Open();
// perform bulk insert
using(var bulk = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.KeepIdentity|SqlBulkCopyOptions.KeepNulls, null))
{
foreach(DataColumn column in table.Columns)
{
bulk.ColumnMappings.Add(column.ColumnName, column.ColumnName);
}
bulk.DestinationTableName = String.Format("[{0}].[{1}]", schemaName, tableName);
bulk.WriteToServer(table);
}
}

Categories