I am using the following code:
string cmd = "INSERT INTO " + Tables.Lux() + " VALUES(NULL, #Position, #Mode, #Timer)";
try
{
using (var MyConnection = new MySqlConnection(ConfigurationManager.ConnectionStrings["DataFormConnection"].ConnectionString))
{
using (MySqlCommand command = new MySqlCommand(cmd, MyConnection))
{
MyConnection.Open();
command.Parameters.Add(new MySqlParameter("Position", Element.Position));
command.Parameters.Add(new MySqlParameter("Mode", Element.Mode));
command.Parameters.Add(new MySqlParameter("Timer", Element.Timer));
command.ExecuteNonQuery();
}
}
}
I am using the above code to insert data from a list of Element containing 100 items. I would like to add 100 values in only one query, and I know that the SQL statement looks like:
INSERT INTO table (a,b) VALUES (1,2), (2,3), (3,4);
but I don't know how to apply that structure using the MySqlCommand.Parameters approach.
My goal is to pass this function List<Element> instead of just Element and create an INSERT statement with all the items in the list to be executed in only one query. Any help please?
Thank you.
Try it like this:
string cmd = "INSERT INTO " + Tables.Lux() + " VALUES ";
int counter = 0;
foreach (Element e in list)
{
sql += "(NULL, #Position" + counter + ", #Mode" + counter + ", #Timer" + counter + "),";
command.Parameters.Add(new MySqlParameter("Position" + counter, e.Position));
command.Parameters.Add(new MySqlParameter("Mode" + counter, e.Mode));
command.Parameters.Add(new MySqlParameter("Timer" + counter, e.Timer));
counter++;
}
command.CommandText = sql.Substring(0, sql.Length-1); //Remove ',' at the end
This way you can have a variable number of parameters in your query and you only have to fire it once against the database, not n times
This is untested, just out of my head!
I used #xenogenesis answer to solve my problem, maybe can help someone else
List<EntregadorRPC.Address> addresstoinsert = eoSendAddressList.addresses;
int batteryLvl = eoSendAddressList.batteryLevel;
DateTime dtHoraLocal;
int size = addresstoinsert.Count;
const string insertHeader = "Insert into historicolocalizacao (Provedor, CodUsuario, Latitude, Longitude, Precisao, Logradouro, " +
"Complemento, Setor, Cidade, UF, Cep, DataHoraLocal, bateria) Values";
StringBuilder insertValues = new StringBuilder("");
using (MySqlCommand cmd = new MySqlCommand()) {
for (int i = 0; i < size; i++) {
EntregadorRPC.Address address = addresstoinsert[i];
dtHoraLocal = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
dtHoraLocal = dtHoraLocal.AddMilliseconds(address.dataHoraLocal).ToLocalTime();
/*address.logradouro = WSUtils.RemoveSpecialCharacters(address.logradouro);
address.formattedAddress = WSUtils.RemoveSpecialCharacters(address.formattedAddress);*/
cmd.Parameters.AddWithValue($"#provedor{i}", address.provedor);
cmd.Parameters.AddWithValue($"#user_id{i}", user.user_id);
cmd.Parameters.AddWithValue($"#latitude{i}", address.latitude);
cmd.Parameters.AddWithValue($"#longitude{i}", address.longitude);
cmd.Parameters.AddWithValue($"#precisao{i}", address.precisao);
cmd.Parameters.AddWithValue($"#logradouro{i}", address.logradouro);
cmd.Parameters.AddWithValue($"#complemento{i}", address.complemento);
cmd.Parameters.AddWithValue($"#setor{i}", address.setor);
cmd.Parameters.AddWithValue($"#cidade{i}", address.cidade);
cmd.Parameters.AddWithValue($"#uf{i}", address.uf);
cmd.Parameters.AddWithValue($"#cep{i}", address.cep);
cmd.Parameters.AddWithValue($"#datahoralocal{i}", dtHoraLocal.ToString("yyyy-MM-dd HH:mm:ss"));
cmd.Parameters.AddWithValue($"#bateria{i}", batteryLvl);
insertValues.Append($"(#provedor{i}, #user_id{i}, #latitude{i}, #longitude{i}, #precisao{i}, #logradouro{i}, #complemento{i}, #setor{i}, #cidade{i}, #uf{i}, #cep{i}, #datahoralocal{i}, #bateria{i})");
if (i < size - 1) {
insertValues.Append(",");
}
}
cmd.Connection = conn;
cmd.CommandText = $"{insertHeader}{insertValues}";
await cmd.ExecuteNonQueryAsync();
}
Related
Okay, so i'm trying to get 18 "prices" from my database in SQL, then setting them in a local array. So far i have this logic in the data retrieval:
private void dbPrices()
{
string myConnectionString;
myConnectionString = "server=127.0.0.1;uid=root;" +
"pwd=;database=phvpos";
try
{
conn = new MySql.Data.MySqlClient.MySqlConnection();
conn.ConnectionString = myConnectionString;
conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message);
}
for (int i = 1; i < 19; i++)
{
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT price from products where id = '" + i + "'";
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
pr[i] = reader.ToString();
prods[i] = int.Parse(pr[i]);
}
}
}
And this logic in getting the total amount:
private void btnTotal_Click(object sender, EventArgs e)
{
dbPrices();
itemcost[0] = Convert.ToInt32(txtRice.Text) * prods[0];
itemcost[1] = Convert.ToInt32(txtAdobo.Text) * prods[1];
itemcost[2] = Convert.ToInt32(txtIgado.Text) * prods[2];
itemcost[3] = Convert.ToInt32(txtSisig.Text) * prods[3];
...
itemcost[18] = itemcost[0] + itemcost[1] + itemcost[2] + itemcost[3] + itemcost[4] + itemcost[5]
+ itemcost[6] + itemcost[7] + itemcost[8] + itemcost[9] + itemcost[10]
+ itemcost[11] + itemcost[12] + itemcost[13] + itemcost[14] + itemcost[15]
+ itemcost[16] + itemcost[17];
int totalPrice = itemcost[18];
lblTotal.Text = Convert.ToString(totalPrice);
}
this line in dbPrices() spits out a 'input string was not in a correct format' error:
while (reader.Read())
{
pr[i] = reader.ToString();
prods[i] = int.Parse(pr[i]);
}
I have also tried:
while (reader.Read())
{
prods[i] = Convert.toInt32(reader.ToString());
}
But also spits the same error. Is there anything that i'm doing wrong?
Try this. I find that when using 'reader' that even when your query only grabs one value you still need to specify what value your looking for.
prods[i] = int.Parse(reader["price"]);
and if price is nullable in the database use a ternary operator
prods[i] = reader["price"] == DBNull.Value ? 0 : int.parse(reader["price"]);
The value from your result needs to convert to int and your for loop block might cause you serious problem in the future, you might want to have a projection query and then assign the values of the result.
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = $"SELECT price FROM products WHERE id BETWEEN 1 AND 18"; //use projection. if you have a dynamic product id set, you can use IN in query.
MySqlDataReader reader = cmd.ExecuteReader();
var counter = 0; //counter
while (reader.Read())
{
prods[counter] = Convert.ToInt32(reader["price"]); //convert the result first then assign it to the item.
counter++;
}
I have a datagridview which is created by various action and user's manipulation of data. I want to insert all the data of the gridview to the database at once, I know I could try a code similar to this:
private void btnSaveProducts_Click(object sender, EventArgs e)
{
SqlConnection connection = DBConnectivity.getConnection();
if (connection != null)
{
try
{
for (int i = 0; i < dGvProducts.Rows.Count; i++)
{
string query = "INSERT INTO product (productName) " + "VALUES (#productName)";
SqlCommand command = DBConnectivity.getCommandForQuery(query, connection);
int result = command.ExecuteNonQuery();
Console.WriteLine(result + "");
}
// string query = "Insert into units(name,packing)values('" + txtNameUnit.Text + "' , '" + txtPackingUnit.Text + "')";
// SqlCommand command = DBConnectivity.getCommandForQuery(query, connection);
// int result = command.ExecuteNonQuery();
// Console.WriteLine(result + "");
}
catch (Exception ex)
{
}
finally
{
connection.Close();
}
}
}
As is, the code tries to execute a parameterized query but never assigns a value to the parameter. Even if you do, you never extract the cell values.
The code should look like this:
var query = "INSERT INTO product (productName) VALUES (#productName)";
using var(connection = DBConnectivity.getConnection())
using(var command = new SqlCommand(query, connection))
{
var productParam=command.Parameters.Add("#productName",SqlDbType.NVarChar,50);
connection.Open();
for (int i = 0; i < dGvProducts.Rows.Count; i++)
{
var productName=dGvProducts.Rows[i].Cells[somecolumn].Value;
productParam.Value=productName;
int result = command.ExecuteNonQuery();
Console.WriteLine(result);
}
}
I need select the maximum ID of PolygonId column. I save my data like this
string sql = "create table Polygons (PolygonId int, PointId int, X double, Y double)";
// Выполнение нашей команды
using (SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection))
{
command.ExecuteNonQuery();
}
int pointId = 1;
for (int i = 0; i < listOfCustomPolygons.Count; i++)
for (int j = 0; j < listOfCustomPolygons[i].listOfVertexes.Count; j++)
{
string strSQL =
string.Format("INSERT INTO Polygons (PolygonId,PointId,X,Y) Values ('{0}','{1}','{2}','{3}')",
i+1,pointId,listOfCustomPolygons[i].listOfVertexes[j].X,
listOfCustomPolygons[i].listOfVertexes[j].Y );
pointId++;
using (SQLiteCommand insertCommand = new SQLiteCommand(strSQL, m_dbConnection))
{
insertCommand.ExecuteNonQuery();
}
}
After this I want select the max value from table Polygons and column PolygonId, but I got an IndexOutOfRangeException. How a can solve this problem?
using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + openFileDialog.FileName + ";Version=3;"))
{
connection.Open();
string selectMaxId = "Select Max(PolygonId) From Polygons";
string selectQuery = "Select * From Polygons";
SQLiteCommand selectMaxCmd = new SQLiteCommand(selectMaxId,connection);
SQLiteDataReader dataReader = selectMaxCmd.ExecuteReader();
int maxId = Convert.ToInt32(dataReader["Select Max(PolygonId) From Polygons"]); // This is don't work! Why?
I found out the solution! It should look like
string selectMaxId = "Select Max(PolygonId) From Polygons";
SQLiteCommand selectMaxCmd = new SQLiteCommand(selectMaxId,connection);
object val = selectMaxCmd.ExecuteScalar();
int maxId = int.Parse(val.ToString());
I hope it can help somebody who face with similar problem)
First of all don't create table every time you run your code :) But you probably know that
You type like this:
int maxId = Convert.ToInt32(dataReader["Select Max(PolygonId) From Polygons"]);
Try this:
string selectMaxId = "Select Max(PolygonId) From Polygons";
SQLiteCommand selectMaxCmd = new SQLiteCommand(selectMaxId,connection);
SQLiteDataReader dataReader = selectMaxCmd.ExecuteReader();
int maxID = -1;
while(dataReader.read())
{
maxID = (int)dataReader.GetValue(0);
}
//This Works for me in WPF C#:
int MaxNum=0;
sqliteCon.Open();
string Query = "SELECT MAX(Promo_No)FROM Promo_File";
SQLiteCommand createCommand = new SQLiteCommand(Query, sqliteCon);
SQLiteDataReader DR = createCommand.ExecuteReader();
while (DR.Read())
{
MaxNum = DR.GetInt16(0);
}
sqliteCon.Close();
I had the same problem!
You have to learn the difference method of SQLiteCommand.
1.SQLiteCommand.ExecuteReader(). Get a SqlDataReader.
2.SQLiteCommand.ExecuteScalar(). Get a single value from the database.
Microsoft Doc:
cmd.CommandText = "SELECT COUNT(*) FROM dbo.region";
Int32 count = (Int32) cmd.ExecuteScalar();
My question, which is similar to this one, is how can I use OracleDataReader to retrieve all the fields for a given record? Currently, I've been using this method, which returns only one column value at a time:
public string Select_File(string filename, string subdirectory, string envID)
{
Data_Access da = new Data_Access();
OracleConnection conn = da.openDB();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename ='" + filename + "'"
+ " AND Subdirectory = '" + subdirectory + "'"
+ " AND Environment_ID = '" + envID + "'";
cmd.CommandType = CommandType.Text;
string x;
OracleDataReader dr = cmd.ExecuteReader();
if (dr.HasRows) // file exists in DB
{
dr.Read();
x = dr.GetString(2).ToString(); // return baseline filename (index 2)
}
else
{
x = "New File";
}
cmd.Dispose();
da.CloseDB(conn);
return x;
}
I'm sure that this method is far from perfect and ppl will be quick to point that out (I was basically given it by my supervisor since I didn't have any prior experience in ASP.NET) but all I really care about is that it works. My question is: how can it be modified to return all the fields for a given record?
The fields will be of either VARCHAR2, CHAR, or DATE datatypes, (if that makes a difference) and some of these values may be null. I'm thinking I could convert them to strings and return them as a list?
if u want something like this:
List<User> lstUser = new List<User>();
string sqlQuery = "Select * from User_T where User_Name='" + oUser.UserName + "' And Password='" +oUser.Password + "' AND IsActive='"+1+"' AND IsDelete='"+0+"'";
string connectionString = "Data Source=ORCL;User Id=ACCOUNTS;Password=ACCOUNTS";
using (DBManager dbManager = new DBManager(connectionString))
{
try
{
dbManager.Open();
OracleDataReader dataReader = dbManager.ExecuteDataReader(sqlQuery);
while (dataReader.Read())
{
oUser = new User();
oUser.Id = Convert.ToInt32(dataReader["ID"]);
oUser.CompanyId = Convert.ToInt32(dataReader["Company_ID"]);
oUser.BranchId = Convert.ToInt32(dataReader["Branch_ID"]);
oUser.UserName = Convert.ToString(dataReader["User_Name"]);
lstUser.Add(oUser);
}
dataReader.Close();
dataReader.Dispose();
}
catch
(Exception)
{
}
finally
{
dbManager.Close();
dbManager.Dispose();
}
To read all the data from the columns of the current row in a DataReader, you can simply use GetValues(), and extract the values from the array - they will be Objects, of database types.
Object[] values;
int numColumns = dr.GetValues(values); //after "reading" a row
for (int i = 0; i < numColumns; i++) {
//read values[i]
}
MSDN - "For most applications, the GetValues method provides an efficient means for retrieving all columns, rather than retrieving each column individually."
Sorry for posting an answer to a very old question. As none of the answers are correct (either they have security issues or not checking for DBNull), I have decided to post my own.
public async Task<StringBuilder> FetchFileDetailsAsync(string filename, string subdirectory, string envId)
{
var sb = new StringBuilder();
//TODO: Check the parameters
const string connectionString = "user id=userid;password=secret;data source=" +
"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.8)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xe)))";
const string selectQuery = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename = :filename"
+ " AND Subdirectory = :subdirectory"
+ " AND Environment_ID = :envID"
+ " AND rownum<=1";
using (var connection = new OracleConnection(connectionString))
using (var cmd = new OracleCommand(selectQuery, connection) {BindByName = true, FetchSize = 1 /*As we are expecting only one record*/})
{
cmd.Parameters.Add(":filename", OracleDbType.Varchar2).Value = filename;
cmd.Parameters.Add(":subdirectory", OracleDbType.Varchar2).Value = subdirectory;
cmd.Parameters.Add(":envID", OracleDbType.Varchar2).Value = envId;
//TODO: Add Exception Handling
await connection.OpenAsync();
var dataReader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection);
var rowValues = new object[dataReader.FieldCount];
if (dataReader.Read())
{
dataReader.GetValues(rowValues);
for (var keyValueCounter = 0; keyValueCounter < rowValues.Length; keyValueCounter++)
{
sb.AppendFormat("{0}:{1}", dataReader.GetName(keyValueCounter),
rowValues[keyValueCounter] is DBNull ? string.Empty : rowValues[keyValueCounter])
.AppendLine();
}
}
else
{
//No records found, do something here
}
dataReader.Close();
dataReader.Dispose();
}
return sb;
}
i face the following problem::
i wanna to escape the following character ' single quote:
it works when making this test through :the built in method Replace("'","''");
as this code below :(just a test) it works
protected void btn_insert_Click(object sender, EventArgs e)
{
lbl.Text = string.Empty;
SqlConnection mycon = new SqlConnection(Constr);`
SqlCommand mycommand = new SqlCommand("INSERT INTO details VALUES('" + txt.Text.Replace("'", "''") + "','" + txt.Text.Replace("'", "''")+ "')", mycon);
mycon.Open();
int affectedRows = 0;
affectedRows = mycommand.ExecuteNonQuery();
mycon.Close();
}
but i wanna to generalize my solution to work all over the application through my Insert method in the data access layer:
public static int InsertEntity(string tblName, Dictionary<string, string> dtParams)
{
int Result = -1;
DBConnection DAL_Helper = new DBConnection("");
string[] field_names = new string[dtParams.Count];
dtParams.Keys.CopyTo(field_names, 0);
string[] field_values = new string[dtParams.Count];
dtParams.Values.CopyTo(field_values, 0);
for (int i = 0; i < field_values.Length; i++)
{
field_values[i].Replace("'", "''");
}
string insertCmd = "INSERT INTO " + tblName + " (" + string.Join(",", field_names) + ") values ('" + string.Join("','", field_values) + "')";
Result = DAL_Helper.Execute_NonQuery(insertCmd);
return Result;
}
this not escaping the ' single quote charecter,although i use Replace("'","''");
what is the problem ,,how to fix this problem?
I strongly recommend you use Command Parameters using SqlCommand.Parameters collection instead of your approach.
Problem is here :
for (int i = 0; i < field_values.Length; i++)
{
field_values[i].Replace("'", "''");
}
Replace it with :
for (int i = 0; i < field_values.Length; i++)
{
field_values[i] = field_values[i].Replace("'", "''");
}
Building on decyclone's answer. CommandParameters are the way to go here, you are just re-inventing it with your own code.
I have found a very nice clear example here for supplying params to a SQL statement.
http://dotnetperls.com/sqlparameter
using (SqlCommand command = new SqlCommand("SELECT * FROM Dogs1 WHERE Name LIKE #Name", connection))
{
string dogName = "Mc'Dougal";
//
// Add new SqlParameter to the command.
//
command.Parameters.Add(new SqlParameter("Name", dogName));
//
// Read in the SELECT results.
//
SqlDataReader reader = command.ExecuteReader();
}