Update sql table from datatable - c#

Using C# .net 4.0 and visual studio 2010.
I need to update a table on my server with a table that is generated in my code.
I'm having difficulty figuring out what I need to do.
Do I need to update or do I need to create a temp table with and insert? or something totally different.
public void SaveMyWorkI()
{
DataGridViewRowCollection coll = ParetoGrid.Rows;
saveTable.Columns.Add("Part", typeof(string));
saveTable.Columns.Add("Pareto", typeof(string));
foreach (DataGridViewRow item in coll)
{
saveTable.Rows.Add(item.Cells[2].Value, item.Cells[5].Value);
//saveTable.Rows.Add(item.Cells[5].Value);
}
MyErrorGrid.DataSource = saveTable;
//SqlCommand pgINSERT = new SqlCommand("INSERT or UPDATE", conn);
}
The update would inner join on part.
As you can see I just did this and now my mind has gone blank. Not only that but this is the last major part to the small program.
Here's what i have so far:
foreach (DataGridViewRow item in coll)
{
saveTable.Rows.Add(item.Cells[2].Value, item.Cells[5].Value);
part = item.Cells[2].Value.ToString();
pareto = item.Cells[5].Value.ToString();
SqlCommand pgINSERT = new SqlCommand("UPDATE dbo.OldParetoAnalysis SET part = " + part + " , pareto = " + pareto + "", conn);
pgINSERT.ExecuteReader();
//saveTable.Rows.Add(item.Cells[5].Value);
}
Error I'm getting is "Invalid column name 'BK177'", BK177 is my data from my 1st row 1st column.

so basically you have a DataTable with data and you want to insert all its content on the DB?
You didn't say which version of SQL Server you are using but if you are using 2008, there is a table valued parameter type that you can use to send a whole table to a procedure for example. Then you could read this table on the proc and do whatever you need to do with it.
References:
http://msdn.microsoft.com/en-us/library/bb510489.aspx
http://msdn.microsoft.com/en-us/library/bb675163.aspx
http://blog.sqlauthority.com/2008/08/31/sql-server-table-valued-parameters-in-sql-server-2008/

Related

Querying the row of an ADO.NET sql database given the value of its first column (C#, Xamarin)

My C# skillset is very limited. My code background is MATLAB, FORTRAN, and more recently, Python. I've used Xamarin in visual studio to bootstrap a smart device application for a quick demonstration internally.
Elsewhere in this application I create a SQLite database with ADO.NET, and populate it with entries the user selects from pickers, spinners, and text entry. Each row is a 'profile' for that person.
Now, another portion of the app takes the first column (Profile Names) and populates a spinner such that a user can select themselves thusly:
//Check if database exists and get rider names for selection
bool exists = File.Exists(pathToDatabase);
string nameString = string.Empty;
if (exists)
{
Console.WriteLine("Reading database");
var connection = new SqliteConnection("Data Source=" + pathToDatabase);
connection.Open();
using (var contents = connection.CreateCommand())
{
contents.CommandText = "SELECT [Name] FROM Riders";
var r = contents.ExecuteReader();
while (r.Read())
nameString += (r["Name"].ToString() + ",");
connection.Close();
}
}
//Populate spinner with Rider Names
string[] nameList = nameString.Split(',');
var ridernameAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerItem, nameList);
ridernameAdapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
RiderSelectSpinner.Adapter = ridernameAdapter;
This works great, the names appear in my spinner, and the user can select them.
The reason I'm here, is I want to now get all the rest of the data in that row associated with the profile when they select themselves, given the value of the first column (the name).
I have all the code that recognizes when they select themselves. Can someone guide me in forming a query in ADO.NET that gets the rest of the row given the first row entry? Something like below?
contents.CommandText = "SELECT * FROM Riders WHERE [Name] = #Name"; //FIX
contents.Parameters.AddWithValue("#Name", Name);
Thanks for your time and help.
var conn = new SQLite.Net.SQLiteConnection(plat, path);
var resunt = conn.Table<Riders>().FirstOrDefault(x => x.Name == name); //Using LINQ or
or
var conn = new SQLite.Net.SQLiteConnection(plat, path);
var resunt = conn.Query<Riders>("SELECT * FROM [Riders] WHERE [Name]=" + name);

DataGridView Datatable Copy-Keep-Add-Update rows

I am developing Windows application (environment: Visual Studio 2010 and C#)
I use a datagridview with records completed by datatable dt:
dataGridView1.DataSource = dt;
This datatable has 20 columns with 1 identity column - column[0] = autonumber, and column[1] called “RecordChecked” implemented as Boolean (checkbox).
I need to solve next problems:
Select rows filtered by column[2] (in code example: DrawingNo='DM-3012');
Keep these records
Add exactly the same records below existing but update column[2] with different value like DrawingNo='DM-3013' (so we’ll have twice more records)
I started from copying records from one datatable into another (see code below) – this code works ok, but then stacked how to add copied records below existing and then update them:
DataTable dtSource = ((DataTable)dataGridView1.DataSource);
DataTable dtTarget = new DataTable();
dtTarget = ((DataTable)dataGridView1.DataSource).Clone();
DataRow[] rowsToCopy;
rowsToCopy = ((DataTable)dataGridView1.DataSource).Select("DrawingNo='DM-3012'");
foreach (DataRow temp in rowsToCopy)
{
dtTarget.ImportRow(temp);
}
dt = dtTarget;
Thanks,
I think I found a good approach to this problem.
1. Create Stored Procedure (mySP).
This SP creates temp table where we located all records selected with clause 'WHERE DrawingNo = #CopyFrom'.
Then this SP updates temp table with statement like:
UPDATE #TempTbl1 SET RecChecked = 0, DrawingNo = #CopyTo WHERE DrawingNo = #CopyFrom.
Then SP inserts updated records from temp table into the main table.
Finally SP drops temp table and selects all needed records from the main table.
2. Now we can run this SP in app and bind data to datagridview like:
//Run SP
using (SqlCommand cmd = new SqlCommand("mySP", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#CopyFrom", SqlDbType.VarChar).Value = sValueFrom;
cmd.Parameters.Add("#CopyTo", SqlDbType.VarChar).Value = sValueTo;
con.Open();
cmd.ExecuteNonQuery();
}
//Create SELECT statement
string strSelect = "SELECT Recid, RecChecked, DrawingNo, ... FROM Tbl1 WHERE DrawingNo = '" + sValueTo + "'"
//fill dataadapter
sda = new SqlDataAdapter(#strSelect, con);
dt = new DataTable();
sda.Fill(dt);
That works!

How to get table name of a column from SqlDataReader

I have an SQL query I get from a configuration file, this query usually contains 3-6 joins.
I need to find at run time, based on the result set represented by SqlDataReader, to find the name of the table for each column.
Here are some thing that don't work:
SqlDataReader.GetName returns the column name but not the table name.
SqlDataReader.GetSchemaTable returns a data table with column information - but all the table names are null.
Querying information_schema doesn't help because I need data on the results of the current query (and the column names are not unique - there are columns with the same name in different tables).
I'm using .net 3.5SP1/ C#/ SQL Server 2008 in a console application.
EDIT: I know this is not possible for all cases since a "column" can be combined from multiple tables, a function or even a constant expression - I'm looking for something that works in the simple case.
EDIT 2: Found out why it didn't work - You can use SqlDataReader.GetSchemaTable to get table information but you have to set CommandBehavior to KeyInfo, you do that in the ExecuteReader call:
reader = cmd.ExecuteReader(CommandBehavior.KeyInfo);
You can use SqlDataReader.GetSchemaTable to get table information but you have to set CommandBehavior to KeyInfo, you do that in the ExecuteReader call:
reader = cmd.ExecuteReader(CommandBehavior.KeyInfo);
This unanswered question on stackoverflow uses SqlDataReader.GetSchemaTable to get the table name. Their problem is that it returns the actual table name rather than the alias that the table has. Not sure if this works with your sql but figured I'd let you know just in case.
I don't know if this information is available. In particular, not all columns of a result set come from a table. From a relational point of view, tables and resultsets are the same thing.
reader = cmd.ExecuteReader();
reader.GetSchemaTable().Rows[0]["BaseTableName"];
In general, this is not possible. Consider the following query:
SELECT col1 FROM table1
UNION ALL
SELECT col1 FROM table2
Clearly col1 comes from more than one table.
you can solve it like the following :
DataTable schemaTable = sqlReader.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows)
{
foreach (DataColumn column in schemaTable.Columns)
{
MessageBox.Show (string.Format("{0} = {1}", column.ColumnName, row[column]));
}
}
SqlCeConnection conn = new SqlCeConnection("Data Source = Database1.sdf");
SqlCeCommand query = conn.CreateCommand();
query.CommandText = "myTableName";
query.CommandType = CommandType.TableDirect;
conn.Open();
SqlCeDataReader myreader = query.ExecuteReader(CommandBehavior.KeyInfo);
DataTable myDataTable= myreader.GetSchemaTable();
//thats the code you asked. in the loop
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
listView1.Columns.Add(myDataTable.Rows[i][0].ToString());
}
How to get database name, table name & column name.
Also possible to get Schema name as well. Tested with MS SQL 2016
CommandBehavior.KeyInfo must be indicated
SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(CommandBehavior.KeyInfo);
DataTable dataTable = sqlDataReader.GetSchemaTable();
for (int i = 0; i < dataTable.Rows.Count - 1; i++)
{
string ii =
dataTable.Rows[i]["BaseCatalogName"].ToString() + "\\" +
dataTable.Rows[i]["BaseTableName"].ToString() + "\\" +
dataTable.Rows[i]["ColumnName"].ToString();
}

How to update a large table using ADO.NET

Ok, so here's the problem I have to solve. I need to write a method in C# that will modify a table in SQL Server 2008. The table could potentially contain millions of records. The modifications include altering the table by adding a new column and then calculating and setting the value of the new field for every row in the table.
Adding the column is not a problem. It's setting the values efficiently that is the issue. I don't want to read in the whole table into a DataTable and then update and commit for obvious reasons. I'm thinking that I would like to use a cursor to iterate over the rows in the table and update them one by one. I haven't done a whole lot of ADO.NET development, but it is my understanding that only read-only server side (firehose) cursors are supported.
So what is the correct way to go about doing something like this (preferably with some sample code in C#)? Stored procedures or other such modifications to the DB are not allowed.
jpgoody,
Here is an example to chew on using the NerdDinner database and some SQLConnection, SQLCommand, and SQLDataReader objects. It adds one day to each of the Event Dates in the Dinners table.
using System;
using System.Data.SqlClient;
namespace NerdDinner
{
public class Class1
{
public void Execute()
{
SqlConnection readerConnection = new SqlConnection(Properties.Settings.Default.ConnectionString);
readerConnection.Open();
SqlCommand cmd = new SqlCommand("SELECT DinnerID, EventDate FROM Dinners", readerConnection);
SqlDataReader reader = cmd.ExecuteReader();
SqlConnection writerConnection = new SqlConnection(Properties.Settings.Default.ConnectionString);
writerConnection.Open();
SqlCommand writerCommand = new SqlCommand("", writerConnection);
while (reader.Read())
{
int DinnerID = reader.GetInt32(0);
DateTime EventDate = reader.GetDateTime(1);
writerCommand.CommandText = "UPDATE Dinners SET EventDate = '" + EventDate.AddDays(1).ToString() + "' WHERE DinnerID = " + DinnerID.ToString();
writerCommand.ExecuteNonQuery();
}
}
}
}
Your problem looks like something that you should be solving using T-SQL and not C#, unless there is some business rule that you are picking up dynamically and calculating the column values T-SQL should be the way to go. Just write a stored procedure or just open up Management studio and write the code to make your changes.
If this does not help then please elaborate on what exactly you want to do to the table, then we can help you figure out if this can be done via T-SQL or not.
[EDIT] you can do something like this
string sql = " USE " + paramDbName;
sql+= " ALTER TABLE XYZ ADD COLUMN " + param1 + " datatype etc, then put semicolon to separate the commands as well"
sql+= " UPDATE XYZ SET Columnx = " + some logic here
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
get this executed on the required instance of Sql Server 2008.
If you have too many lines of text then use StringBuilder.
Here's a suggestion:
You can read data using a DataReader , create a update command for current row and add it to a list of commands.Then run update commands in a transaction.
something like this:
var commands=new List<SqlCommand>();
while(dr.Read())
{
var cmd=new SqlCommand();
cmd.CommandText="Add your command text here";
commands.Add(cmd);
}
using(var cnn=new SqlConnection("Connection String"))
{
IDbTransaction transaction;
try
{
cnn.Open();
transaction=cnn.BeginTransaction();
foreach(var cmd in commands)
{
cmd.Transaction=transaction;
cmd.ExecuteNonQuery();
cmd.Dispose();
}
transaction.Commit();
}
catch(SqlException)
{
if(transaction!=null)
transaction.Rollback();
throw;
}
}

C# Dynamically Add Columns to table in Database

I am still learning quite a bit about programming so this may be an obvious question but I am in the process of writing a program where a user can import an excel file with no column constraints (meaning each excel file could have a different number of columns and so on). What I want to do is be able to convert the imported excel file into a database table using SQLite. As far as I have read the syntax for SQLite is the same as ADO syntax but I am unsure of how to dynamically create the tables in the database. I am looking for any form of suggestions, if someone felt like showing an example in code that would be cool.
Thanks!
Nathan
Here is a piece of code for creating a table in sqlite:
SQLiteConnection mDBcon = new SQLiteConnection();
mDBcon.ConnectionString = "Data Source=" + DataSourcePath;
mDBcon.Open();
SQLiteCommand cmd = new SQLiteCommand(mDBcon);
cmd.CommandText = "CREATE TABLE IF NOT EXISTS tags (ISBN VARCHAR(15), Tag VARCHAR(15));";
cmd.ExecuteNonQuery();
note that in SQLite you can only add coloumn to existing tables, and only to the end of the table:
cmd.CommandText = "ALTER TABLE books ADD COLUMN PublishDate DateTime;";
cmd.ExecuteNonQuery();
Addition
Assuming you imported you data from the excel to a DataSet,
you can now iterate through the DataSet's DataTables, create the corresponding tables and fill them:
(disclaimer, haven't tested it)
foreach(DataTable table in dataSet.Tables)
{
SQLiteCommand cmd = new SQLiteCommand(mDBcon);
cmd.CommandText = "CREATE TABLE IF NOT EXISTS " + table.Name + "(";
bool first = true;
foreach (DataColumn column in table.Columns)
{
cmd.CommandText += "#"+column.Name;
if (!first) cmd.CommandText += ",";
else first = false;
cmd.Parameters.Add(new SQLiteParameter("#"+column.Name, column.Name));
}
cmd.CommandText += ");";
cmd.ExecuteNonQuery();
// Fill the new table:
SQLiteDataAdapter da = new SQLiteDataAdapter("select * from " + table.Name, mDBcon);
da.Fill(table);
}
You can just use ExecuteNonQuery to create your table, using the standard SQLite Query Language for CREATE TABLE.

Categories