I'm gathering a list of users and their information that I would like to store in a database table. I have this database set up in Microsoft SQL Server Management Studio. The primary key of the database is set to auto-incrementing. I need the loop to end when there are no more users in the list. I have two valid users in the test account however what I currently have only inserts a single user. Would I be better off to use a sqlDataAdapter?
List<User> result = ims.ListUsers(req).ListUsersResult.Users;
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ConnectionString);
for (int i = 1; i < result.Count(); i++)
{
foreach (User user in result.Where(x => x.UserName.Contains('#')))
{
string sql = #"INSERT INTO UserInfo (UserID, UserName) VALUES (#UserID, #UserName)";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#UserID", i);
command.Parameters.AddWithValue("#UserName", user.UserName);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
}
I don't understand why you need the outer for-loop to create the ID since you should not set the primary key column manually. It will increment automatically. You should also always close a connection when you're finished
Here is the complete code:
string sql = #"INSERT INTO UserInfo (UserName) VALUES (#UserName)";
using(var con = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ConnectionString))
using(var cmd = new SqlCommand(sql, con))
{
con.Open();
foreach(var user in result.Where(x => x.UserName.Contains('#')))
{
// you don't need to set the UserID when you've set made it an Identity column
cmd.Parameters.AddWithValue("#UserName", user.UserName);
cmd.ExecuteNonQuery();
}
}
I think you need to replace:
for (int i = 1; i < result.Count(); i++)
With:
for (int i = 0; i < result.Count(); i++)
Your problem is that you have 2 loops. You need to remove the first for loop and instead increment a int variable each time you execute through your foreach()
You are adding multiple users with the same UserID
int userID = 1
foreach (User user in result.Where(x => x.UserName.Contains('#')))
{
// your code
userID++;
}
You do not need to update auto-incrementing field, it will count automatically by SQL server. Try this code:
List<User> result = ims.ListUsers(req).ListUsersResult.Users;
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ConnectionString);
foreach (User user in result.Where(x => x.UserName.Contains('#')))
{
string sql = #"INSERT INTO UserInfo (UserName) VALUES (#UserName)";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#UserName", user.UserName);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
Related
I am trying to update a databse entry under a specific id in my table when the users enter their ID number in a textBox.
At the moment it updates but updates all entries in my table except the entry containing the users ID number.
This is the code I am currently using:
private void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=DEVELOPMENT\ACCESSCONTROL;Initial Catalog=ACCESSCONTROL;User ID=sa;Password=P#55w0rd123");
SqlCommand check_User_Name = new SqlCommand("SELECT Id FROM NewVisitor WHERE (IDNumber = #IDNumber)", con);
check_User_Name.Parameters.AddWithValue("#IDNumber", idNumber_TxtBox.Text);
con.Open();
int UserExist = (int)check_User_Name.ExecuteScalar();
if (UserExist > 0)
{
var connetionString = #"Data Source=DEVELOPMENT\ACCESSCONTROL;Initial Catalog=ACCESSCONTROL;User ID=sa;Password=P#55w0rd123";
var sql = "UPDATE NewVisitor SET PersonVisit = #PersonVisit, PurposeVisit = #PurposeVisit, Duration = #Duration, Disclaimer = #Disclaimer";
try
{
using (var connection = new SqlConnection(connetionString))
{
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#PersonVisit", SqlDbType.NVarChar).Value = personVisiting_TxtBox.Text;
command.Parameters.Add("#PurposeVisit", SqlDbType.NVarChar).Value = purposeOfVisit_CMBox.SelectedItem;
command.Parameters.Add("#Duration", SqlDbType.Date).Value = duration_dateTimePicker1.Value.Date;
command.Parameters.Add("#Disclaimer", SqlDbType.NVarChar).Value = disclaimer_CHKBox.Checked;
connection.Open();
command.ExecuteNonQuery();
}
}
}
The whole table has many more fields but would like to just update the above fields within that specific ID.
Thanks
You forgot the WHERE clause on the UPDATE statement, telling it specifically which records to update. It sounds like you just want to add the exact same WHERE clause that you have on your SELECT:
var sql = "UPDATE NewVisitor SET PersonVisit = #PersonVisit, PurposeVisit = #PurposeVisit, Duration = #Duration, Disclaimer = #Disclaimer WHERE (IDNumber = #IDNumber)";
And don't forget to add the paramter for it:
command.Parameters.Add("#IDNumber", SqlDbType.Int).Value = idNumber_TxtBox.Text;
You may need to convert the input value to an integer first, I'm not 100% certain (it's been a while since I've had to use ADO.NET directly). Something like this:
if (!int.TryParse(idNumber_TxtBox.Text, out var idNumber))
{
// input wasn't an integer, handle the error
}
command.Parameters.Add("#IDNumber", SqlDbType.Int).Value = idNumber;
I have tried to give multiple insert or update in single query like
OleDbCommand command = new OleDbCommand("INSERT INTO Employee (Id,
Name, Address, Salary) VALUES (2001, 'name1', 'address1',
100000);UPDATE Employee SET Salary = 2000000 WHERE Id = 2001;");
This executes successfully.
But I don't want multiple sql queries in single execution. Is there anything like any property or something like that in C# which can be used to restrict to only one query.
I want to restrict it to single sql query in single execution.
Thanks.
Try something like this
Create a stringbuilder of values
StringBuilder sb = new StringBuilder();
string sep = "";
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
sb.AppendFormat("value1","value2" etc);
}
string insertthis = sb.ToString();
Then insert to sql
using (OleDbCommand cmd = new OleDbCommand("INSERT INTO Employee (ItemName) VALUES (#ins)", con))
{
cmd.Parameters.AddWithValue("#ins", insertthis );
cmd.ExecuteNonQuery();
}
MessageBox.Show("Data added");
Update also works like same as insert
Ref
I need to change my field QB_STATUS from value R to value C. I am doing this in a loop because i cannot "requery" the table as data may have changed.
I have built a list of entries to update. The code does not error and iterates through 5 times (correct based on my idInvoices list) but the field does not get updated.
for (int i = 0; i < idInvoices.Count; i++)
{
// following command will update one row as ID_Invoice is primary key.
// ID_Invoice taken from list previously built in ReadDataToNAVArray
SqlCommand cmd = new SqlCommand("UPDATE tblINVOICES SET QB_STATUS=#Status WHERE ID_INVOICE = #IDInvoice", myConnection);
cmd.Parameters.Add("#Status", "C");
cmd.Parameters.Add("#IDInvoice", idInvoices[i]);
cmd.Dispose();
}
First, you have to execute your query: ExecuteNonQuery; second - do not create command, parameters etc within the loop, just assign values and execute:
// Make SQL readable
String sql =
#"UPDATE tblINVOICES
SET QB_STATUS = #Status
WHERE ID_INVOICE = #IDInvoice";
// wrap IDisposable into "using"
// do not recreate command in the loop - create it once
using (SqlCommand cmd = new SqlCommand(sql, myConnection)) {
cmd.Parameters.Add("#Status", SqlDbType.VarChar); //TODO: check types, please
cmd.Parameters.Add("#IDInvoice", SqlDbType.Decimal); //TODO: check types, please
// Assign parameters with their values and execute
for (int i = 0; i < idInvoices.Count; i++) {
cmd.Parameters["#Status"].Value = "C";
cmd.Parameters["#IDInvoice"].Value = idInvoices[i];
cmd.ExecuteNonQuery();
}
}
You are missing the ExecuteNonQuery in your command.
for (int i = 0; i < idInvoices.Count; i++)
{
SqlCommand cmd = new SqlCommand("UPDATE tblINVOICES SET QB_STATUS=#Status WHERE ID_INVOICE = #IDInvoice", myConnection);
cmd.Parameters.Add("#Status", "C");
cmd.Parameters.Add("#IDInvoice", idInvoices[i]);
cmd.ExecuteNonQuery();
cmd.Dispose();
}
I think you're missing cmd.ExecuteNonQuery();.
An example for a different way of using sql commands:
SqlConnection addConn = new SqlConnection();
addConn.ConnectionString = Properties.Settings.Default.yourDataBaseConnection;
addConn.Open();
SqlCommand addComm = new SqlCommand();
addComm.Connection = addConn;
addComm.CommandText = "sql command";
addComm.ExecuteNonQuery();
I have a simple database that I am using. It contains two entries for users which is a user with UserID 1 and IsAdmin 0 and another with UserID 3041234567 and IsAdmin of 1. The only fields in the database is a string UserID and a bit IsAdmin. I am reading from the database with the following code:
SqlConnection conn = new SqlConnection(Properties.Settings.Default.Conn);
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE UserID = " + t.Text.ToString(), conn);
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
user.UserID = reader["UserID"].ToString();
user.IsAdmin = Convert.ToBoolean(reader["IsAdmin"]);
}
}
conn.Close();
If I enter the number 3041234567 as the UserID everything works perfectly, but If I enter the number 1 I get an exception saying that "The conversion of the nvarchar value '3041234567' overflowed an int column."
If I set a breakpoint and watch the while(reader.read()) loop the loop iterates through fine and sets the user.UserID = 1 and the user.IsAdmin = false. The exception is thrown when the loop begins to iterate a second time. I guess I have a couple of questions:
Why is the loop iterating a second time?
How is the ID 3041234567 being returned with the sql command "SELECT * FROM Users WHERE UserID = 1"
What is the int column that is being overflowed?
Well, since
3041234567 > int.MaxValue ( == 2147483647)
you've got an overflow; if you want some kind of integer value, however, try long (which is 64 bit long):
long value = Convert.ToInt64(reader["UserID"]);
Something like this:
// Wrap IDisposable into using
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.Conn)) {
conn.Open();
// Make sql
// 1. Readable
// 2. Parametrized
// 3. Avoid * in select
String sql =
#"select UserID,
IsAdmin
from Users
where UserID = #prm_UserId";
// Wrap IDisposable into using
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
// Explicit data type will be better here (Add Parameter with type)
// but I don't know it
cmd.Parameters.AddWidthValue("prm_UserId", t.Text);
// Wrap IDisposable into using
using (SqlDataReader reader = cmd.ExecuteReader()) {
// You don't want to iterate the whole cursor, but the first record
if (reader.Read()) {
//TODO: Make UserID being "long"
user.UserID = Convert.ToInt64(reader["UserID"]);
user.IsAdmin = Convert.ToBoolean(reader["IsAdmin"]);
}
}
}
}
I am going to have multiple processes running at the same time so what I tried to do here is fetch 1000 rows and then update the rows i selected.. below are my Select and Update functions notice i call the update function right after closing the connection in the select function
public List<string> Select()
{
string set;
string query = "SELECT * FROM master WHERE attempted='0' LIMIT 1000";
List<string> list = new List<string>();
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (list.Count() < 1000)
{
dataReader.Read();
string email = dataReader["email"].ToString();
var m = dataReader["attempted"];
if (m.ToString() == "0")
{
list.Add(email);
}
}
dataReader.Close();
this.CloseConnection();
Update();
return list;
}
else
{
return list;
}
}
public void Update()
{
if (this.OpenConnection() == true)
{
string query = "UPDATE master SET attempted='1' WHERE ( SELECT * FROM master WHERE attempted='0' LIMIT 1000 )";
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.CommandText = query;
cmd.ExecuteNonQuery();
this.CloseConnection();
}
}
the exception i am getting it operand must contain 1 column(s)..
What am I doing wrong?
Why can't you just create a separate column, or even a table? Then write a basic Query at the SQL level or a Procedure to modify the value? Then the other applications can just test the value of the column or table.
Example:
UPDATE [dbo].[Customer]
SET [GotEmail] = 1
WHERE (
SELECT [Email]
FROM [dbo].[Customer]
);
Or something basic like that? Another example would be:
UPDATE accounts
SET (contact_last_name, contact_first_name) =
(SELECT last_name, first_name FROM salesmen
WHERE salesmen.id = accounts.sales_id);
Does a simple query like so not solve your issue?
If my response is not clear... I'll try and clarify my thought process.