I am creating a Attendance System and using grid view to insert the data. There may be many rows on the grid. All things are going well and data are also entering well. But I am using a for loop to check each row. This make the performance quite slow when the number of rows increases. And also the round trips increases with the growing number of rows.
Can anyone provide a better solution for this?
I have modify my CODE according to u all.....but now a problem has arise it is only inserting the last row of the grid multiple times......Other than this the Code is fine.
MySqlDataAdapter myworkdatta = myworkdatta = new MySqlDataAdapter("SELECT CID,EID,TID,ATTENDENCE FROM EMPLOYEEATT ORDER BY AID DESC LIMIT 1", conn);
DataSet myworkdsatt = new DataSet();
myworkdatta.Fill(myworkdsatt, "EMPLOYEEATT");
int i;
for (i = 0; i < emplist_gv.Rows.Count; i++)
{
string tid = emplist_gv.Rows[i].Cells[6].Value.ToString();
string eid = emplist_gv.Rows[i].Cells[0].Value.ToString();
string atid = emplist_gv.Rows[i].Cells[7].Value.ToString();
MySqlCommand cmdwk = new MySqlCommand("INSERT INTO EMPLOYEEATT (CID,EID,TID,ATTENDENCE) VALUES (#cid,#eid,#tid,#attendence)", conn);
MySqlParameter spcidatt = new MySqlParameter("#cid", calid);
MySqlParameter speid = new MySqlParameter("#eid", eid);
MySqlParameter sptid = new MySqlParameter("#tid", tid);
MySqlParameter spattendence = new MySqlParameter("#attendence", atid);
cmdwk.Parameters.Add(spcidatt);
cmdwk.Parameters.Add(speid);
cmdwk.Parameters.Add(sptid);
cmdwk.Parameters.Add(spattendence);
myworkdatta.InsertCommand = cmdwk;
DataRow drowk = myworkdsatt.Tables["EMPLOYEEATT"].NewRow();
drowk["CID"] = calid;
drowk["EID"] = eid;
drowk["TID"] = tid;
drowk["ATTENDENCE"] = atid;
myworkdsatt.Tables["EMPLOYEEATT"].Rows.Add(drowk);
}
myworkdatta.Update(myworkdsatt, "EMPLOYEEATT");
Considering your 2 select SQL statement doesn't seem to contain anything relevant to the the specific row you can take that out of the loop and just use its values easy enough.
Because you need to do an insert on each row, which I don't understand why, then it seems hard to remove the database hits there.
If you are doing a bulk insert you could look at bulk inserts for MySql: MySql Bulk insert
You can use SqlBulkCopy, it's easy to use. Basically just provide it with a data table (or data reader) and it will copy the rows from that source to your destination table.
Shortly, the code block would look like:
DataTable dataTableInGridView = (DataTable)emplist_gv.DataSource;
using (SqlConnection connection =
new SqlConnection(connectionString))
{
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName =
"dbo.BulkCopyDemoMatchingColumns";
try
{
// Write from the source to the destination.
bulkCopy.WriteToServer(dataTableInGridView);
}
catch (Exception ex)
{
// Handle exception
}
}
}
Related
Can anyone share how to coding copy a datatable to another datatable in faster way for C# sqlite? Thanks.
And also need to change column name also. i tried to manually select and update, but encountered error. Appreciate for your sharing. Thanks.
or how can i amend the column header when display datatable in datagridview? Thanks.
dbConnect = new SQLiteConnection("Data Source=school.db;Version=3;");
dbConnect.Open();
cmd4 = new SQLiteCommand();
cmd4 = dbConnect.CreateCommand();
cmd4.CommandText = "DELETE FROM GroupEven";
cmd4.ExecuteNonQuery();
cmd4.CommandText = "SELECT Day, Day_ID, Standard, Timeslot1_TeacherName, Timeslot1_Subject, Timeslot2_TeacherName, Timeslot2_Subject, Timeslot3_TeacherName, Timeslot3_Subject, Timeslot4_TeacherName, Timeslot4_Subject, Timeslot5_TeacherName, Timeslot5_Subject, Timeslot6, Timeslot7_TeacherName, Timeslot7_Subject, Timeslot8_TeacherName, Timeslot8_Subject, Timeslot9_TeacherName, Timeslot9_Subject, Timeslot10_TeacherName, Timeslot10_Subject, Timeslot11_TeacherName, Timeslot11_Subject FROM TimetableFinal";
DataTable dt4 = new DataTable();
SQLiteDataAdapter da4 = new SQLiteDataAdapter(cmd4);
da4.Fill(dt4);
foreach (DataRow dr4 in dt4.Rows)
{
cmd4.CommandText = "INSERT INTO TimetableFinal2 (Day, Day_ID, Standard, 7:30am-8:00am, 7.30am-8.00am, 8:00am-8:30am, 8.00am-8.30am, 8:30am-9:00am, 8.30am-9.00am, 9:00am-9:30am, 9.00am-9.30am, 9:30am-10:00am, 9.30am-10.00am, 10:00am-10:20am, 10:20am-10:50am, 10.20am-10.50am, 10:50am-11:20am, 10.50am-11.20am, 11:20am-11:50am, 11.20am-11.50am, 11:50am-12:20pm, 11.50am-12.20pm, 12:20pm-12:50pm, 12.20pm-12.50pm) VALUES (#Day, #Day_ID, #Standard, #7:30am-8:00am, #7.30am-8.00am, #8:00am-8:30am, #8.00am-8.30am, #8:30am-9:00am, #8.30am-9.00am, #9:00am-9:30am, #9.00am-9.30am, #9:30am-10:00am, #9.30am-10.00am, #10:00am-10:20am, #10:20am-10:50am, #10.20am-10.50am, #10:50am-11:20am, #10.50am-11.20am, #11:20am-11:50am, #11.20am-11.50am, #11:50am-12:20pm, #11.50am-12.20pm, #12:20pm-12:50pm, #12.20pm-12.50pm)";
cmd4.Parameters.AddWithValue("#Day", dr4["Day"].ToString());
SQLite does support Joinings Insert statements, something like this.
INSERT INTO 'tablename' ('column1', 'column2')
VALUES
('data1', 'data2'),
('data3', 'data4'),
('data5', 'data6'),
('data7', 'data8');
See this.. http://www.sqlite.org/lang_insert.html
and then execute this in one go. Also, Make sure you do this in transactions and wrap around in using statements
using(var dbConnect = new SQLiteConnection("DataSource=school.db;Version=3;"))
{
dbConnect.Open();
using(var transaction = dbConnect.BeginTransaction())
{
string insertQuery = ...// your insert query
using (var cmd = dbConnect.CreateCommand())
{
cmd.CommandText = insertQuery;
foreach (DataRow dr4 in dt4.Rows)
{
cmd.Parameters.AddWithValue(...);
}
cmd.ExecuteNonQuery()
}
transaction.Commit();
}
}
Regarding your second part: How can i amend the column header when display datatable in datagridview,
thats totally separate, has nothing to do with Sqlite insertions.
After getting the data source you can do something like this
dataGridView1.Columns[i].HeaderText = "My New header";
So I am creating a messaging application for a college project and I have a database of Users in Access, I have linked the database correctly and can execute statements but I am struggling with one problem, how to count the number of rows in a data table.
In fact, all I want to do is to count the total number of users and my teacher told me to get the data into a DataTable and count the number of rows. However, no matter how many users I have in the database, it always returns as 2.
int UserCount = 0;
using (OleDbConnection cuConn = new OleDbConnection())
{
cuConn.ConnectionString = #"DATASOURCE";
string statement = "SELECT COUNT(*) FROM Users";
OleDbDataAdapter da = new OleDbDataAdapter(statement, cuConn);
DataTable Results = new DataTable();
da.Fill(Results);
if (Results.Rows.Count > 0)
{
UserCount = int.Parse(Results.Rows[0][0].ToString());
}
}
The above code is a copy of what I was sent by my teacher who said it would work. Any help would be appreciated.
Also, sorry if this is a waste of time, still getting used to this StackOverflow thing...
Try replace Users with [Users]?
Because Users may be a key word of database.
Also the simpler way to get aggregate numbers is by ExecuteScalar method.
using (OleDbConnection cuConn = new OleDbConnection())
{
cuConn.ConnectionString = #"DATASOURCE";
string statement = "SELECT COUNT(*) FROM [Users]";
OleDbCommand cmd = new OleDbCommand (statement, cuConn);
cuConn.Open();
int count = (int)cmd.ExecuteScalar();
if (count > 0)
{
//
}
}
I successfully used your exact code (except the connection string) with sql server so maybe there is a problem with your #"DATASOURCE" or MS Access.
I have never learned this aspect of programming, but is there a way to get each separate result of a excel query(using OleDB) or the likes.
The only way I can think of doing this is to use the INTO keyword in the SQL statement, but this does not work for me (SELECT attribute INTO variable FROM table).
An example would be to use the select statement to retrieve the ID of Clients, and then compare these ID's to clientID's in a client ListArray, and if they match, then the clientTotal orders should be compared.
Could someone prove some reading material and/or some example code for this problem.
Thank you.
This code fetches rows from a sql procedure. Will probably work for you too with some
modifications.
using (var Conn = new SqlConnection(ConnectString))
{
Conn.Open();
try
{
using (var cmd = new SqlCommand("THEPROCEDUREQUERY", Conn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlDataReader reader = cmd.ExecuteReader();
// Find Id of column in query only once at start
var Col1IdOrd = reader.GetOrdinal("ColumnName");
var Col2IdOrd = reader.GetOrdinal("ColumnName");
// loop through all the rows
while (reader.Read())
{
// get data for each row
var Col1 = reader.GetInt32(ColIdOrd);
var Col2 = reader.GetDouble(Col2IdOrd);
// Do something with data from one row for both columns here
}
}
}
finally
{
Conn.Close();
}
Could somebody take a quick peek at my ado.net code? I am trying to update the row from a dataset, but it just isn't working. I am missing some elemental piece of the code, and it is just eluding me. I have verified that the DataRow actually has the correct data in it, so the row itself is accurate.
Many thanks in advance.
try
{
//basic ado.net objects
SqlDataAdapter dbAdapter = null;
DataSet returnDS2 = new DataSet();
//a new sql connection
SqlConnection myConn = new SqlConnection();
myConn.ConnectionString = "Server=myserver.mydomain.com;"
+ "Database=mydatabase;"
+ "User ID=myuserid;"
+ "Password=mypassword;"
+ "Trusted_Connection=True;";
//the sqlQuery
string sqlQuery = "select * from AVLUpdateMessages WHERE ID = 21";
//another ado.net object for the command
SqlCommand cmd = new SqlCommand();
cmd.Connection = myConn;
cmd.CommandText = sqlQuery;
//open the connection, execute the SQL statement and then close the connection.
myConn.Open();
//instantiate and fill the sqldataadapter
dbAdapter = new SqlDataAdapter(cmd);
dbAdapter.Fill(returnDS2, #"AVLUpdateMessages");
//loop through all of the rows; I have verified that the rows are correct and returns the correct data from the db
for (int i = 0; i <= returnDS2.Tables[0].Rows.Count - 1; i++)
{
DataRow row = returnDS2.Tables[0].Rows[i];
row.BeginEdit();
row["UpdatedText"] = #"This is a test...";
row.EndEdit();
}
//let's accept the changes
dbAdapter.Update(returnDS2, "AVLUpdateMessages");
returnDS2.AcceptChanges();
myConn.Close();
}
I think you need an update query in your data adapter. I know, this sucks... Alternatively you can use CommandBuilder class to automatically generate queries for CRUD operations.
example at: http://www.programmersheaven.com/2/FAQ-ADONET-CommandBuilder-Prepare-Dataset
You might be able to use SqlCommandBuilder to help out. After the Fill call, add the following statement. That will associate a command builder with the data adapter and (if there is a primary key available) it should generate the update statement for you. Note that there is some expense behind the command builder. It may not be much relative to everything else, but it does involve looking at schema information (to get primary key information, field names, field types, etc.) for the table and generating INSERT, DELETE, and UPDATE statements involving all fields in the table.
SqlCommandBuilder cb = new SqlCommandBuilder(dbAdapter);
Wait, why not something like
update AVLUpdateMessages set UpdatedText = 'This is a test...' where id = 21
If you're picking through all the rows of a table to update one at a time, you're probably doing it wrong. SQL is your friend.
I have a database table with one field, called ID, being an auto increment integer.
Using a TableAdapter I can read and modify existing rows as well as create new ones.
However if I try to modify a newly inserted row I get an DBConcurrencyException:
OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Shift.mdb;Persist Security Info=True");
ShiftDataSetTableAdapters.ShiftTableAdapter shiftTA = new ShiftDataSetTableAdapters.ShiftTableAdapter();
shiftTA.Connection = conn;
ShiftDataSet.ShiftDataTable table = new ShiftDataSet.ShiftDataTable();
ShiftDataSet.ShiftRow row = table.NewShiftRow();
row.Name = "life";
table.Rows.Add(row);
shiftTA.Update(row); // row.ID == -1
row.Name = "answer"; // <-- all fine up to here
shiftTA.Update(row); // DBConcurrencyException: 0 rows affected
Separate question, is there any static type of the NewShiftRow() method I can use so that I don't have to create table everytime I want to insert a new row.
I guess the problem in the code comes from row.ID that is still -1 after the first Update() call. The Insert is successful and in the database the row has a valid value of ID.
How can I get that ID so that I can continue with the second Update call?
Update:
IT looks like this could have been done automatically using this setting.
However according to the answer on msdn social, OLEDB drivers do not support this feature.
Not sure where to go from here, use something else than oledb?
Update:
Tried SQLCompact but discovered that it had the same limitation, it does not support multiple statements.
Final question: is there any simple(single file based) database that would allow you to get the values of a inserted row.
Try this http://support.microsoft.com/kb/815629 , the sample code is in VB.NET though.
Or if multiline query is accepted in MS Access and it has built-in function/variable for retrieving the last id, use this (the database is SQLite though): anyway see why I get this "Concurrency Violation" in these few lines of code??? Concurrency violation: the UpdateCommand affected 0 of the expected 1 records , try to google for the function
[EDIT: Works on my Machine, I don't have SQL Server Compact, but I didn't use multi-statement]
public Form1()
{
InitializeComponent();
var c = Connect();
var da = new SqlDataAdapter("select emp_id, emp_firstname, emp_lastname from emp where 1 = 0", c);
var b = new SqlCommandBuilder(da);
var getIdentity = new SqlCommand("SELECT CAST(##IDENTITY AS INT)", c);
da.InsertCommand = b.GetInsertCommand();
da.UpdateCommand = b.GetUpdateCommand();
da.DeleteCommand = b.GetDeleteCommand();
da.RowUpdated += (xsender, xe) =>
{
if (xe.Status == UpdateStatus.Continue && xe.StatementType == StatementType.Insert)
{
xe.Row["emp_id"] = (int)getIdentity.ExecuteScalar();
}
};
var dt = new DataTable();
da.Fill(dt);
var nr = dt.NewRow();
nr["emp_firstname"] = "john";
nr["emp_lastname"] = "lennon";
var nrx = dt.NewRow();
nrx["emp_firstname"] = "paul";
nrx["emp_lastname"] = "mccartney";
dt.Rows.Add(nr);
dt.Rows.Add(nrx);
da.Update(dt);
dt.AcceptChanges();
nrx["emp_lastname"] = "simon";
da.Update(dt);
nr["emp_lastname"] = "valjean";
da.Update(dt);
}
SqlConnection Connect()
{
return new SqlConnection(#"data source=.\SQLEXPRESS;Database=Test;uid=sa;pwd=hey");
}
Why not select the MAX(RowId), as your RowId should increment for each INSERT? Is this possible for you?
As for your final answer, SQLite might be the perfect tool for you. I hope so! And it has its own .NET Data Provider, so no need for OLEDB or ODBC providers.