Multiple OleDbCommands producing System Resource Exceeded - c#

So basically I have a C# project, that iterates through every student (300 students) within a table called Student within a Microsoft Access 2016 database. In a single iteration for a single student by using other tables like Mathematics, Reading that have a 1-to-1 relationship with the Student table, to grab the data that belongs to that student.
try
{
OleDbCommand allStudents = new OleDbCommand("SELECT [NSN]"
+ " FROM [Student]; ");
allStudents.Connection = conn;
OleDbDataAdapter allData = new OleDbDataAdapter(allStudents);
DataTable allTable = new DataTable();
allData.Fill(allTable);
foreach (DataRow dr in allTable.Rows)
{
string NSN = dr["NSN"].ToString();
OleDbCommand cmd = new OleDbCommand("SELECT * "
+ "FROM (((([Student] s "
+ "INNER JOIN [Student Extra] se ON se.[NSN] = s.[NSN]) "
+ "INNER JOIN [Reading] r ON r.[NSN] = s.[NSN])"
+ "INNER JOIN [Writing] w ON w.[NSN] = s.[NSN])"
+ "INNER JOIN [Mathematics] m ON m.[NSN] = s.[NSN]) "
+ "WHERE s.[NSN] = '" + NSN + "'; ");
cmd.Connection = conn;
OleDbDataAdapter daa = new OleDbDataAdapter(cmd);
DataTable dtt = new DataTable();
daa.Fill(dtt);
foreach (DataRow drr in dtt.Rows)
{
firstName = drr["Preferred Name"].ToString();
gender = drr["Gender"].ToString();
room = drr["Room Number"].ToString();
NSAchieve = drr["National Standard Achieve"].ToString();
NSProgress = drr["National Standard Progress"].ToString();
The above code is only a snippet of the code I have, but this is basically where the function will start.
By using this data, I want to be able to go through several SELECT statements for other tables and compare them and produce a calculated value.
Dictionary<string, OleDbCommand> d = new Dictionary<string, OleDbCommand>();
cmd = new OleDbCommand("SELECT [Achievement Statement]"
+ " FROM [National Standard Codes]"
+ " WHERE [National Standard Code] = '" + readingNSAchievementCode + "'; ");
d["readingNSAchievementOTJ"] = cmd;
cmd = new OleDbCommand("SELECT [" + NSAchieve + "]"
+ " FROM [Reading National Standards]"
+ " WHERE [Assessment] = '" + readingFinalAssessment + "'; ");
d["readingNSAchievementComp"] = cmd;
cmd = new OleDbCommand("SELECT [Timeframe]"
+ " FROM [Reading Statements]"
+ " WHERE [Year Code] = '" + NSProgress + "'; ");
d["readingNSProgressTimeframe"] = cmd;
There are several more commands, (approx <150). I use a Dictionary to store my Commands, and then execute the commands in a FOREACH loop.
foreach(KeyValuePair<string, OleDbCommand> pair in d)
{
try
{
string v = pair.Key;
OleDbCommand dbCmd = pair.Value;
dbCmd.Connection = conn;
OleDbDataReader reader = dbCmd.ExecuteReader();
reader.Read();
readingDict[v] = reader.GetString(0);
}
catch (Exception e)
{
MessageBox.Show("Error at " + pair.Key + "\n\n Here is message " + e);
}
}
After executing and getting my value, I want to store my data into another table called Calculated.
string insert1 = "INSERT INTO [Calculated] (";
int i = 0;
Dictionary<string, string> dict = createDictionary(NSN);
int len = dict.Count / 2;
foreach (KeyValuePair<string, string> pair in dict)
{
string field = pair.Key;
string value = pair.Value;
if (i == (len - 1))
{
insert1 += "[" + field + "])";
break;
}
else
{
insert1 += "[" + field + "], ";
}
i++;
}
insert1 += " VALUES (";
i = 0;
foreach (KeyValuePair<string, string> pair in dict)
{
string field = pair.Key;
string value = pair.Value;
if (i == len - 1)
{
insert1 += "'" + value + "')";
break;
}
else
{
insert1 += "'" + value + "', ";
}
i++;
}
I build my INSERT INTO query, and then I execute using an OleDbCommand. This needs to repeat 300 times, but for development purposes currently I only have 5 students in my Student table. However when executing after the 4th student it will always consistently give me an error System Resources Exceeded always at a specific OleDbCommand. I have tested each command separately, so there is no issue with the way the OleDbCommands are written.
I have tried searching on here, and tried to encase the first code snippet in a using statement, using using (OleDbConnection conn = new OleDbConnection(connectionStr)) but as I am still a novice at C#, I am unable to produce a solution.

Related

OleDbDataReader does not read last record

I see 5 records to be inserted, but only 4 are inserted. The last record is not inserted, and I can not figure out why. Copying from one database to the other. First is an access database, the second is a sql server database.
OleDbCommand cmd2 = new OleDbCommand();
OleDbDataReader oledbReader2;
using (cmd2 = new OleDbCommand())
{
query = "SELECT ID, STRAATNAAM, 'NL' AS TAALCODE, PKANCODE, CITY FROM Temp_Unique_Streetnames WHERE TRIM(Temp_Unique_Streetnames.STRAATNAAM) <> '' AND ID > " + lastId.ToString() + " ORDER BY ID";
WriteToFile(query);
cmd2.CommandText = query;
cmd2.CommandType = CommandType.Text;
cmd2.Connection = cn2;
using (oledbReader2 = cmd2.ExecuteReader())
{
while (oledbReader2.Read())
{
try
{
counter += 1;
query = "insert into tblgeo_street ( autoid, street_id, language, country, city, streetname, zip) values (" + counter.ToString() +
" , " + oledbReader2.GetValue(0).ToString() +
" , 'NL', 23, " + oledbReader2.GetValue(4).ToString() +
" , '" + oledbReader2.GetValue(1).ToString().Replace('\'', '´') + "'" +
" , " + oledbReader2.GetValue(3).ToString() + ") ";
OleDbCommand cmd3 = new OleDbCommand(query, cn3);
WriteToFile(query);
cmd3.ExecuteNonQuery();
}
catch (Exception errorException)
{
actionSucceedded = false;
//eventLog1.WriteEntry("Open db threw exception " + errorException.Message);
WriteToFile("insert tblgeo_street threw exception " + errorException.Message);
}
}
}
}

How to insert multiple data into database?

i would like to insert multiple data into my database. I am using for-each statement to get the data and when i insert into the database, it generates 10(just a random no. depending on the no. of data i retrieved) rows for me with one data in every row instead of all in one row. here is the for-each statement i am using.
foreach(var kiev in dict)
{
string na = kiev.Key;
if(na != "db_table_name")
{
string quer = "insert into " + HttpContext.Current.Session["tablename"].ToString() + " ( " + kiev.Key + " ) VALUES ( '" + kiev.Value + "' ) ";
SqlCommand cl = new SqlCommand(quer, con);
cl.ExecuteNonQuery();
}
}
There are better options like "SqlBulkCopy" available as already mentioned in the comments but also something like this should work:
string tablename = "";
string values = "";
string keys = "";
foreach(var kiev in dict)
{
string na = kiev.Key;
if(na != "db_table_name")
{
keys += kiev.Key + ", ";
values += "'" + kiev.Value + "', ";
}
}
keys = keys.Remove(keys.Length - 2);
values = values.Remove(values.Length - 2);
string quer = "insert into " + HttpContext.Current.Session["tablename"].ToString() + " ( " + keys + " ) VALUES ( " + values + " ) ";
SqlCommand cl = new SqlCommand(quer, con);
cl.ExecuteNonQuery();

How to get more values from Access c#

I want to select a sentence from the database, but i don't know how to write the code. I will search for a number by reading lines from the textbox.
for (int i = 0; i < lines.GetUpperBound(0); i++)
{
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
string query1 = "SELECT TOP 1 * FROM SolozinnenTabel WHERE Faciliteitnummer = " + lines[i] + " AND Paragraaf LIKE '" + AlineaKinderenNaam + "%' ORDER BY rnd(ID)";
command.CommandText = query1;
OleDbDataReader reader1 = command.ExecuteReader();
while (reader1.Read()) {
RichAccoText.Text = RichAccoText.Text + reader1["Zin"].ToString();
RichFacilityText.Lines = RichFacilityText.Lines.Where(line => line != lines[i]).ToArray();
}
}
This code works but I only can search for one line and search them in the textbox. So I want something like this:
string query1 = "SELECT TOP 1 * FROM CombizinnenTabel WHERE (Faciliteitnummer1= " + lines[a] + " AND Faciliteitnummer2= " + lines[a] + ") AND Paragraaf LIKE '" + AlineaAccommodatieNaam + "%' ORDER BY rnd(ID)";
lines[a] = 80, but I want to search:
If Faciliteitnummer1 = lines[80] en Faciliteitnummer2 = lines[48]and Faciliteitnummer3 = lines[18], then select this sentence.....
If (Faciliteitnummer1 = lines[80] en Faciliteitnummer2 = lines[10]and Faciliteitnummer3 = lines[0], then select this sentence....

Check if a record exists in the database

I am using these lines of code to check if the record exists or not.
SqlCommand check_User_Name = new SqlCommand("SELECT * FROM Table WHERE ([user] = '" + txtBox_UserName.Text + "') ", conn);
int UserExist = (int)check_User_Name.ExecuteScalar();
But I am getting an error:
Object reference not set to an instance of an object.
I want to do:
if (UserExist > 0)
// Update record
else
// Insert record
ExecuteScalar returns the first column of the first row. Other columns or rows are ignored. It looks like your first column of the first row is null, and that's why you get NullReferenceException when you try to use the ExecuteScalar method.
From MSDN;
Return Value
The first column of the first row in the result set, or a null
reference if the result set is empty.
You might need to use COUNT in your statement instead which returns the number of rows affected...
Using parameterized queries is always a good practise. It prevents SQL Injection attacks.
And Table is a reserved keyword in T-SQL. You should use it with square brackets, like [Table] also.
As a final suggestion, use the using statement for dispose your SqlConnection and SqlCommand:
SqlCommand check_User_Name = new SqlCommand("SELECT COUNT(*) FROM [Table] WHERE ([user] = #user)" , conn);
check_User_Name.Parameters.AddWithValue("#user", txtBox_UserName.Text);
int UserExist = (int)check_User_Name.ExecuteScalar();
if(UserExist > 0)
{
//Username exist
}
else
{
//Username doesn't exist.
}
The ExecuteScalar method should be used when you are really sure your query returns only one value like below:
SELECT ID FROM USERS WHERE USERNAME = 'SOMENAME'
If you want the whole row then the below code should more appropriate.
SqlCommand check_User_Name = new SqlCommand("SELECT * FROM Table WHERE ([user] = #user)" , conn);
check_User_Name.Parameters.AddWithValue("#user", txtBox_UserName.Text);
SqlDataReader reader = check_User_Name.ExecuteReader();
if(reader.HasRows)
{
//User Exists
}
else
{
//User NOT Exists
}
sqlConnection.Open();
using (var sqlCommand = new SqlCommand("SELECT COUNT(*) FROM Table WHERE ([user] = '" + txtBox_UserName.Text + "'", sqlConnection))
{
SqlDataReader reader = sqlCommand.ExecuteReader();
if (reader.HasRows)
{
lblMessage.Text ="Record Already Exists.";
}
else
{
lblMessage.Text ="Record Not Exists.";
}
reader.Close();
reader.Dispose();
}
sqlConnection.Close();
MySqlCommand cmd = new MySqlCommand("select * from table where user = '" + user.Text + "'", con);
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
DataSet ds1 = new DataSet();
da.Fill(ds1);
int i = ds1.Tables[0].Rows.Count;
if (i > 0) {
// Exist
}
else {
// Add
}
I would use the "count" for having always an integer as a result
SqlCommand check_User_Name = new SqlCommand("SELECT count([user]) FROM Table WHERE ([user] = '" + txtBox_UserName.Text + "') " , conn);
int UserExist = (int)check_User_Name.ExecuteScalar();
if (UserExist == 1) //anything different from 1 should be wrong
{
//Username Exist
}
try this
public static bool CheckUserData(string phone, string config)
{
string sql = #"SELECT * FROM AspNetUsers WHERE PhoneNumber = #PhoneNumber";
using (SqlConnection conn = new SqlConnection(config)
)
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("#PhoneNumber", phone);
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (reader.HasRows)
{
return true; // data exist
}
else
{
return false; //data not exist
}
}
}
}
Use try catch:
try
{
SqlCommand check_User_Name = new SqlCommand("SELECT * FROM Table WHERE ([user] = '" + txtBox_UserName.Text + "') ", conn);
int UserExist = (int)check_User_Name.ExecuteScalar();
// Update query
}
catch
{
// Insert query
}
You can write as follows:
SqlCommand check_User_Name = new SqlCommand("SELECT * FROM Table WHERE ([user] = '" + txtBox_UserName.Text + "') ", conn);
if (check_User_Name.ExecuteScalar()!=null)
{
int UserExist = (int)check_User_Name.ExecuteScalar();
if (UserExist > 0)
{
//Username Exist
}
}
I was asking myself the same question, and I found no clear answers, so I created a simple test.
I tried to add 100 rows with duplicate primary keys and measured the time needed to process it. I am using SQL Server 2014 Developer and Entity Framework 6.1.3 with a custom repository.
Dim newE As New Employee With {.Name = "e"}
For index = 1 To 100
Dim e = employees.Select(Function(item) item.Name = "e").FirstOrDefault()
If e Is Nothing Then
employees.Insert(newE)
End If
Next
2.1 seconds
Dim newE As New Employee With {.Name = "e"}
For index = 1 To 100
Try
employees.Insert(newE)
Catch ex As Exception
End Try
Next
3.1 seconds
sda = new SqlCeDataAdapter("SELECT COUNT(regNumber) AS i FROM tblAttendance",con);
sda.Fill(dt);
string i = dt.Rows[0]["i"].ToString();
int bar = Convert.ToInt32(i);
if (bar >= 1){
dt.Clear();
MetroFramework.MetroMessageBox.Show(this, "something");
}
else if(bar <= 0) {
dt.Clear();
MetroFramework.MetroMessageBox.Show(this, "empty");
}
protected void btnsubmit_Click(object sender, EventArgs e)
{
string s = #"SELECT * FROM tbl1 WHERE CodNo = #CodNo";
SqlCommand cmd1 = new SqlCommand(s, con);
cmd1.Parameters.AddWithValue("#CodNo", txtid.Text);
con.Open();
int records = (int)cmd1.ExecuteScalar();
if (records > 0)
{
Response.Write("<script>alert('Record not Exist')</script>");
}
else
{
Response.Write("<script>alert('Record Exist')</script>");
}
}
private void insert_data()
{
SqlCommand comm = new SqlCommand("Insert into tbl1(CodNo,name,lname,fname,gname,EmailID,PhonNo,gender,image,province,district,village,address,phonNo2,DateOfBirth,school,YearOfGraduation,exlanguage,province2,district2,village2,PlaceOfBirth,NIDnumber,IDchapter,IDpage,IDRecordNumber,NIDCard,Kankur1Year,Kankur1ID,Kankur1Mark,Kankur2Year,Kankur2ID,Kankur2Mark,Kankur3Year,Kankur3ID,Kankur3Mark) values(#CodNo,N'" + txtname.Text.ToString() + "',N'" + txtlname.Text.ToString() + "',N'" + txtfname.Text.ToString() + "',N'" + txtgname.Text.ToString() + "',N'" + txtemail.Text.ToString() + "','" + txtphonnumber.Text.ToString() + "',N'" + ddlgender.Text.ToString() + "',#image,N'" + txtprovince.Text.ToString() + "',N'" + txtdistrict.Text.ToString() + "',N'" + txtvillage.Text.ToString() + "',N'" + txtaddress.Value.ToString() + "','" + txtphonNo2.Text.ToString() + "',N'" + txtdbo.Text.ToString() + "',N'" + txtschool.Text.ToString() + "','" + txtgraduate.Text.ToString() + "',N'" + txtexlanguage.Text.ToString() + "',N'" + txtprovince1.Text.ToString() + "',N'" + txtdistrict1.Text.ToString() + "',N'" + txtvillage1.Text.ToString() + "',N'" + txtpbirth.Text.ToString() + "','" + txtNIDnumber.Text.ToString() + "','" + txtidchapter.Text.ToString() + "', '" + txtidpage.Text.ToString() + "','" + txtrecordNo.Text.ToString() + "',#NIDCard,'" + txtkankuryear1.Text.ToString() + "','" + txtkankurid1.Text.ToString() + "','" + txtkankurscore1.Text.ToString() + "','" + txtkankuryear2.Text.ToString() + "','" + txtkankurid2.Text.ToString() + "','" + txtkankurscore2.Text.ToString() + "','" + txtkankuryear3.Text.ToString() + "','" + txtkankurid3.Text.ToString() + "','" + txtkankurscore3.Text.ToString() + "')", con);
flpimage.SaveAs(Server.MapPath("~/File/") + flpimage.FileName);
string img = #"~/File/" + flpimage.FileName;
flpnidcard.SaveAs(Server.MapPath("~/Tazkiera/") + flpnidcard.FileName);
string img1 = #"~/Tazkiera/" + flpnidcard.FileName;
comm.Parameters.AddWithValue("CodNo", Convert.ToInt32(txtid.Text));
comm.Parameters.AddWithValue("image", flpimage.FileName);
comm.Parameters.AddWithValue("NIDCard", flpnidcard.FileName);
comm.ExecuteNonQuery();
con.Close();
Response.Redirect("~/SecondPage.aspx");
//Response.Write("<script>alert('Record Inserted')</script>");
}
}
Use the method Int.Parse() instead. It will work.
I had a requirement to register user. In that case I need to check whether that username is already present in the database or not. I have tried the below in C# windows form application(EntityFramework) and it worked.
var result = incomeExpenseManagementDB.Users.FirstOrDefault(x => x.userName == registerUserView.uNameText);
if (result == null) {
register.registerUser(registerUserView.fnameText, registerUserView.lnameText, registerUserView.eMailText, registerUserView.mobileText, registerUserView.bDateText, registerUserView.uNameText, registerUserView.pWordText);
} else {
MessageBox.Show("User Alreay Exist. Try with Different Username");
}

Automatically Update Values in Database from DataGridView

I'm currently working on a project using MySql in combination with C#.
The Data for the DataGridView is provided by a join from multiple tables in the DB. To show the data I use the following, working, code:
adapter.SelectCommand = new MySqlCommand(
" SELECT" +
" l.lot AS Lot, "+
" m.comment AS Bemerkungen," +
... (multiple columns from different tables) ...
" FROM m " +
" JOIN m2p ON m.m2p_id = m2p.id" +
... (more joins) ...
, this._mySqlConnection);
dataGridView1.DataSource = data;
adapter.Fill(data);
Now the user of the GUI is allowed to modify a certain column (the "comment" column). So I assigned an eventHandler to the CellEndEdit event and when the user modified the allowed column the adapter.Update(data) is called. Now this doesn't perform the correct action.
To define my updatecommand I used the following code:
adapter.UpdateCommand = new MySqlCommand(
" UPDATE m" +
" JOIN l ON m.l_id = l.id" +
" SET m.comment = #comment" +
" WHERE l.lot = #lot"
, this._mySqlConnection);
adapter.UpdateCommand.Parameters.Add("#comment", MySqlDbType.Text, 256, "Bemerkungen");
adapter.UpdateCommand.Parameters.Add("#lot", MySqlDbType.Text, 256, "Lot");
Could you explain me how I fix my code to automatically Update the database?
EDIT:
added further source code:
private MySqlDataAdapter warenlagerMySqlDataAdapter, kundenMySqlDataAdapter;
private DataTable warenlagerData, kundenData;
private DataGridView warenlagerGridView;
private void updateWarenlagerView(object sender, EventArgs e) {
warenlagerMySqlDataAdapter.Update(warenlagerData);
}
private void initialzeFields() {
warenlagerGridView.CellEndEdit += new DataGridViewCellEventHandler(this.updateWarenlagerView);
warenlagerMySqlDataAdapter = new MySqlDataAdapter();
warenlagerData = new DataTable();
}
private void initializeWarenlagerView() {
warenlagerMySqlDataAdapter.SelectCommand = new MySqlCommand(
" SELECT" +
" c.name AS Ursprung, " +
" m2p.art_nr AS ArtNr," +
" m.delivery_date AS Eingangsdatum," +
" CONCAT(FORMAT(m.delivery_amount / 100, 2), 'kg') AS Eingangsmenge, " +
" l.lot AS Lot," +
" m.quality AS Qualität," +
" m.comment AS Bemerkungen," +
" CONCAT(m.units, 'kg') AS Units," +
" CONCAT(FORMAT(s.amount / 100, 2), 'kg') AS Lagermenge, " +
" FORMAT(m.base_price / 100, 2) AS Einkaufspreis," +
" FORMAT(s.amount/10000 * m.base_price, 2) AS Wert" +
" FROM mushrooms AS m " +
" JOIN mushroom2path AS m2p ON m.mushroom2path_id = m2p.id" +
" JOIN countries AS c ON m.origin_id = c.id" +
" JOIN lots AS l ON m.lot_id = l.id" +
" JOIN stock AS s ON s.mushrooms_id = m.id"
, this._mySqlConnection);
warenlagerGridView.DataSource = warenlagerData;
warenlagerMySqlDataAdapter.Fill(warenlagerData);
warenlagerMySqlDataAdapter.UpdateCommand = new MySqlCommand(
" UPDATE mushrooms AS m" +
" JOIN lots AS l ON m.lot_id = l.id" +
" SET m.comment = #comment" +
" WHERE l.lot = #lot"
, this._mySqlConnection);
warenlagerMySqlDataAdapter.UpdateCommand.Parameters.Add("#comment", MySqlDbType.Text, 256, "Bemerkungen");
warenlagerMySqlDataAdapter.UpdateCommand.Parameters.Add("#lot", MySqlDbType.Text, 256, "Lot");
}
This is the whole code concerning this problem. I'm 100% sure the adapter.Update(data) method is called (debugging). And the data which is passed to the adapter.Update() method contains the new data.
Please try this update query it works.
UPDATE mushrooms
SET comment = #comment
WHERE
l_id=(select id from l where lot=#lot)
Your update statement is incorrect. It should be:
"UPDATE m FROM mushrooms m JOIN lots l ON m.lot_id = l.id SET m.comment = #comment WHERE l.lot = #lot"
Did you forget to execute the warenlagerMySqlDataAdapter.UpdateCommand?
You are just setting the command and the parameters but not executing it.
What I see is that you are calling the update when the info is updated, but your update command is not loaded.
You just call updateWarenlagerView when you update the row, but where are you calling initialzeFields?
Or am I missing code?
Try moving your update code from the CellEndEdit event to the CellValueChanged event and see if this works.
Try this example out:
public void UpdateAllFromDgv(DataGridView dataGridView1)
{
string query = "Update List set ColumnName1=#Value1" +
",ColumnName2=#Value2" +
",ColumnName3=#Value3" +
",ColumnName4=#Value4" +
",ColumnName5=#Value5" +
",ColumnName6=#Value6 where ColumnName0=#Value0";
try
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
using (MySqlConnection con = new MySqlConnection(ConnectionString))
{
using (MySqlCommand cmd = new MySqlCommand(query, con))
{
cmd.Parameters.AddWithValue("#Value0", row.Cells[0].Value);
cmd.Parameters.AddWithValue("#Value1", row.Cells[1].Value);
cmd.Parameters.AddWithValue("#Value2", row.Cells[2].Value);
cmd.Parameters.AddWithValue("#Value3", row.Cells[3].Value);
cmd.Parameters.AddWithValue("#Value4", row.Cells[4].Value);
cmd.Parameters.AddWithValue("#Value5", row.Cells[5].Value);
cmd.Parameters.AddWithValue("#Value6", row.Cells[6].Value);
con.Open();
cmd.ExecuteNonQuery();
dataGridView1.ResetBindings();
con.Close();
}
}
}
}
catch (MySqlException MsE)
{
MessageBox.Show(MsE.Message.ToString());
}
}

Categories

Resources