Insert using listview in c# - c#

My code for processing an insert query:
for (int i = 0; i <= ListView1.Items.Count - 1; i++)
{
con = new OleDbConnection(cn);
string cd = "INSERT INTO ProductSold(ID, invoiceID, description, rate, ps_quantity, ps_mrp, free, totalamount) VALUES (#ID,'" + txtInvoiceNo.Text + "',#description,#Rate,#Quantity,#MRP,#free,#Totalamount)";
cmd = new OleDbCommand(cd);
cmd.Connection = con;
cmd.Parameters.AddWithValue("InvoiceNo", txtInvoiceNo.Text);
cmd.Parameters.AddWithValue("ID", ListView1.Items[i].SubItems[0].Text);
cmd.Parameters.AddWithValue("description", ListView1.Items[i].SubItems[1].Text);
cmd.Parameters.AddWithValue("Rate", ListView1.Items[i].SubItems[5].Text);
cmd.Parameters.AddWithValue("Quantity", ListView1.Items[i].SubItems[2].Text);
cmd.Parameters.AddWithValue("MRP", ListView1.Items[i].SubItems[3].Text);
cmd.Parameters.AddWithValue("free", ListView1.Items[i].SubItems[4].Text);
cmd.Parameters.AddWithValue("Totalamount", ListView1.Items[i].SubItems[6].Text);
con.Open();
cmd.ExecuteNonQuery(); `enter code here`/*error*/
con.Close();
}
Error: insert into table error on data mismatch on criteria?

You are probably messing up with the parameter value types, for some RDBMS they need to be of same type as the field they are referring to (your ID field may be an integer field, but you are using a string value from a TextBox for the ID parameter.
BTW: You are opening a new connection for each entry in your list view. Move the con declaration / assignment out of the loop.

Related

inserting all the data from multiple list-boxes to a table in the database C#

I'm trying to insert all the data from 3 list-boxes to a table in the database i don't know if i'm doing well , this is the code i used
private void Order()
{
using (SqlConnection connection = new SqlConnection(connectionString1))
{
String query = "INSERT INTO Tbl_order (OrderName,Quantity,Price,Serves_way,Date) VALUES (#OrderName,#Quantity, #Price,'"+servers+"','" + time1.ToString(format1)+"' )";
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
for (int i = 0; i < lst_OrderName.Items.Count; i++)
{
string OrderName = lst_OrderName.GetItemText(lst_OrderName.GetSelected(i));
command.Parameters.AddWithValue("#OrderName", lst_OrderName.GetItemText(lst_OrderName.GetSelected(i)));
command.Parameters.AddWithValue("#Quantity", lst_QTY.GetItemText(lst_QTY.GetSelected(i)));
command.Parameters.AddWithValue("#Price", lst_Price2.GetItemText(lst_Price2.GetSelected(i)));
command.Parameters.Add("#OrderName", SqlDbType.NVarChar);
command.Parameters.Add("#Quantity", SqlDbType.Int);
command.Parameters.Add("#Price", SqlDbType.Money);
command.Parameters.Add("#OrderName", SqlDbType.NVarChar).Value = OrderName;
command.Parameters.Add("#Quantity", SqlDbType.Int).Value = Convert.ToInt32(lst_QTY.GetSelected(i));
command.Parameters.Add("#Price", SqlDbType.Money).Value = Convert.ToDouble(lst_Price2.GetSelected(i));
}
// command.Parameters.AddWithValue("#OrderName", lst_OrderName.GetItemText(lst_OrderName.SelectedItem));
//command.Parameters.AddWithValue("#Quantity", lst_QTY.GetItemText(lst_QTY.SelectedItem));
//command.Parameters.AddWithValue("#Price", lst_Price2.GetItemText(lst_Price2.SelectedItem));
int result = command.ExecuteNonQuery();
// Check Error
if (result < 0)
Console.WriteLine("Error inserting data into Database!");
}
}
}
and i have a problem which is says
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: The variable name '#OrderName' has already been declared. Variable names must be unique within a query batch or stored procedure.
this is the pic of the three list-boxes [![enter image description here][1]][1]
What is wrong in code what did i miss?
I want the data to be inserted in the database for each row like how does it look like in the pic .
You're trying to re-add the same parameters multiple times in a loop before ever executing the query. Even in a single iteration of the loop, you try to add every parameter three times. The error is telling you that you can only add the same parameter once.
Move the entire lifespan of the query to inside the loop. Something like this:
connection.Open();
for (int i = 0; i < lst_OrderName.Items.Count; i++)
{
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Parameters.Add("#OrderName", SqlDbType.NVarChar).Value = OrderName;
command.Parameters.Add("#Quantity", SqlDbType.Int).Value = Convert.ToInt32(lst_QTY.GetSelected(i));
command.Parameters.Add("#Price", SqlDbType.Money).Value = Convert.ToDouble(lst_Price2.GetSelected(i));
command.ExecuteNonQuery();
}
}
This would also be a good time to learn about using transactions with a database. That way you can wrap all of these inserts in a single transaction and commit or rollback as needed.

sql query to show data from price between two columns C#

EDIT: I am not able to format my code below, if any one can fix it.
I am new to sql queries and still learning.
Table Name: CommissionSetupTable.
I want to display #Paisa if gross_amount is between the range of #FromRate and #ToRate
Below is my code:
string paisa;
private void load_commission_setup()
{
SqlCeConnection conn = null;
SqlCeCommand cmd = null;
SqlCeDataReader rdr = null;
try
{
conn =
new SqlCeConnection(
#"Data Source=|DataDirectory|\Database.sdf;Persist Security Info=False");
conn.Open();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
gross_amount = double.Parse(purchaseBillTableDataGridView[10, rowindex].Value.ToString());
// Gross Amount is between the ranges of FromRate and ToRate.
cmd = new SqlCeCommand("SELECT Paisa FROM CommissionSetupTable WHERE='" + gross_amount.ToString() + "' BETWEEN #FromRate AND #ToRate;", conn);
rdr = cmd.ExecuteReader();
if (rdr == null)
{
}
else
{
while (rdr.Read())
{
paisa = rdr["Paisa"].ToString();
}
rdr.Close();
cmd.Dispose();
}
}
finally
{
conn.Close();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
purchaseBillTableDataGridView[11, rowindex].Value = paisa;
}
}
The correct syntax to use here is the following
cmd = new SqlCeCommand(#"SELECT Paisa FROM CommissionSetupTable
WHERE #gross BETWEEN FromRate AND ToRate;", conn);
Notice that the two field names should not be prefixed with #, otherwise they will be considered parameters placeholders.
And now, before executing the command, add the parameter for the #gross placeholder
cmd.Parameters.Add("#gross", SqlDbType.Decimal).Value = gross_amount;
I don't know what is the exact datatype of the columns FromRate and EndRate, but
note that you should use the correct datatype for your parameter. Do not pass a string and expect the database engine do the conversion for you. (or worse concatenate your value to the rest of the sql using ToString()). This is always wrong also if sometime the database engine could understand your values.
EDIT
Also, following your comments below, it appears that this line is wrong
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
If your DataGridView has the property AllowUserToAddRow set to True then you want to use
int rowindex = purchaseBillTableDataGridView.Rows.Count - 2;
because the first line points to the empty row added to the DataGridView for inserting a new record.

Auto generate and AutoIncrement ID in C# when trying to add new record to database

I'm using this code to select the maxID from a database table and each time I want to add a new record, the autogenerated ID is not the last one +1.
public formularAddCompanie()
{
InitializeComponent();
try
{
string cs = "Data Source=CODRINMA\\CODRINMA;Initial Catalog=TrafficManager;Integrated Security=True";
string select = "SELECT max(IDCompanie) FROM Companii";
using (SqlConnection con = new SqlConnection(cs))
{
con.Open();
SqlCommand cmd2 = new SqlCommand(select, con);
SqlDataReader sda = cmd2.ExecuteReader();
DataTable idmax = new DataTable("idmax");
idmax.Load(sda);
if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }
else { txtID.Text = (int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }
}
}
catch (Exception er) { MessageBox.Show(er.Message); }
}
The table from where the selection is made, looks like this:
IDCompany Name Address City RegNo
1 A Street NY 123
Each time I want to add a new record, the autogenerated ID is like this: 11, 111, 1111. It takes the last ID and add another 1 next to it. What am I missing?
Interestingly, note that
string a = "The meaning of life is " + 42;
converts 42 to a string, creating the result
a == "The meaning of life is 42"
Look at this code:
(int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }
You are converting idmax.Rows[0][0] to a string and adding +1 to the end of the string rather than to an integer value. Try
(int.Parse(idmax.Rows[0][0].ToString()) + 1).ToString(); }
Note that idmax.Rows[0][0] should already have an integer in it (as pointed out in the comments). If that's the case, you can simplify to
(idmax.Rows[0][0] + 1).ToString(); }
idmax.Rows[0][0].ToString() + 1 produces string, not int.
You can try
txtID.Text = (Convert.ToInt32(idmax.Rows[0][0]) + 1).ToString();
I just add this because it seems that none cares about the weakness of the code posted by the poster.
First the MAX function is not reliable if you want to find the next autoincrement value that will be assigned to an ID column. Concurrency could wreak havoc with any schema that use MAX. Just suppose that another user has already retrieved the MAX for its own INSERT operation, then depending on the relative speed of the two computers you or the other user will insert a duplicate value for the IDCompany field.
The only correct way to do this common task is to use the IDENTITY property for the column IDCompany and when you need to insert a new record you should write something like this
try
{
string insert = "INSERT INTO Companii (Name,Address,City,RegNo)
VALUES(#name,#address,#city,#regno);
SELECT SCOPE_IDENTITY()";
using (SqlConnection con = new SqlConnection(cs))
using (SqlCommand cmd = new SqlCommand(insert, con))
{
con.Open();
cmd.Parameters.Add("#name", SqlDbType.NVarChar).Value = txtBoxCity.Text;
.... and on for the other parameters ....
int companyID = Convert.ToInt32(cmd.ExecuteScalar());
... work with the just added company if required
}
}
catch (Exception er)
{ MessageBox.Show(er.Message); }
SCOPE_IDENTITY will return the last identity value inserted into an identity column in the same scope and in this context scope means the connection used by your command.
In any case, if the MAX approach is still required then the code could be simplified a lot using a modified query and SqlCommand.ExecuteScalar instead of building an SqlDataReader, filling a datatable, trying to parse the result with ifs
string getMax = #"select COALESCE(MAX(IDCompany), 0) + 1 AS maxPlusOne
from Companii"
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(getMax, cnn))
{
cnn.Open();
int nextCompanyID = Convert.ToInt32(cmd.ExecuteScalar());
}
The COALESCE function checks the result of the MAX function and if it is NULL returns the second parameter (here 0), then just increment by 1 to get the next MAX directly from the database. ExecuteScalar will do the call returning just the maxPlusOne alias field
try this snippet:
Convert Your String into Int. String with + operator will con-cat and with int it will add numbers.
if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }
else {
txtID.Text = Convert.ToString(Convert.ToInt32(idmax.Rows[0][0] .ToString())+1); }
Try This one, my id format is USR001.The code will generate auto id based on the last id inside the database. If the last id in the database is USR001, the the code will generate USR002 and put the id to the textbox
con.Open();
string sqlQuery = "SELECT TOP 1 kode_user from USERADM order by kode_user desc";
SqlCommand cmd = new SqlCommand(sqlQuery, con);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
string input = dr["kode_user"].ToString();
string angka = input.Substring(input.Length - Math.Min(3, input.Length));
int number = Convert.ToInt32(angka);
number += 1;
string str = number.ToString("D3");
txtKodeUser.Text = "USR" + str;
}
con.Close();

inserting arraylist values into database

i have used a checkbox list in my project .am storing all the checked items values in arraylist using code below
ArrayList services= new ArrayList();
for (int i = 0; i < chkservices.Items.Count; i++)
{
if (chkservices.Items[i].Selected == true)
{
services.Add(chkservices.Items[i].Text+',');
}
}
now the problem is when i insert data in to database instead of data in the arraylist it gets inserted as 'System.Collections.ArrayList' how can i insert all values into database in a single insert statement?
EDIT
inserting into database
con.Open();
SqlCommand cmd = new SqlCommand("insert into XXX(First_Name,Last_Name,ServicesProvided) values ('" + txtfrstname.Text + "','" + txtlastname.Text + "','" + services + "')", con);
cmd.ExecuteNonQuery();
con.Close();
or could anyone provide me a alternative for arraylist..i need to save checked items from checkboxlist and save it in database
it should be saved in database as
First_Name Last_name ServicesProvided
user1firstname user1lastname selectedvalue1,
selectedvalue2,selectedvalue3
Why not to concatenate your data using the following code:
var mydata = String.Join(',', chkservices.Items
.Where( a => a.Selected).Select( b => b.Text));
So you can add your data as a string.
EDIT:
It is a very bad habit of concatenating strings to make a query! Apart from many side effects like in your case here it is a great security breach. Try the parameterized query instead:
SqlCommand cmd = new SqlCommand(
#"insert into XXX(First_Name,Last_Name,ServicesProvided) values
(#First_Name,#Last_Name,#ServicesProvided")", con);
cmd.Parameters.AddWithValue("#ServicesProvided", mydata);
cmd.Parameters.AddWithValue("#First_Name", frstname.Text);
cmd.Parameters.AddWithValue("#Last_Name", txtlastname.Text);
cmd.ExecuteNonQuery();
mydata is the variable from my first example.
You need to get the values of the array list and send them one by one
or create a stored procedure where you send all the values to using Alexanders Galkins example (or use the a Aggregate method). Then use the split function to split up the string and insert all the record
Using INSERT INTO statement you can insert only one row at a time unless you're using sub query to select data from other table.
As you don't have the data in the database, your only option is iterate over the array and insert each value as new row.
Don't use ArrayList, you have generic list for what you need:
List<string> services = new List<string>();
for (int i = 0; i < chkservices.Items.Count; i++)
{
if (chkservices.Items[i].Selected == true)
{
services.Add(chkservices.Items[i].Text);
}
}
//...connection stuff....
strSQL = "INSERT INTO MyTable (MyField) VALUES (#val)"
using (SqlCommand command = new SqlCommand(strSQL, connection))
{
command.Parameters.AddWithValue("#val", "");
foreach (string service in services)
{
command.Parameters["#val"].Value = service;
command.ExecuteNonQuery();
}
}
How many checkbox do you have? If you just have a little checkbox, so I suggest you transform each state of them into bit mask which represent a number, then store it to database.
long bitMask = 0; // All uncheck
for (int i = 0; i < chkServices.Items.Count; ++i) {
if (chkServices.Items[i].Checked) {
bitMask |= (1 << i);
}
}
// Store bitMask to Database
In later, you can get state via bitMask again when needed.

How to get the SqlType of a column in a DataTable?

I have a DataTable obtained from a SQL DataBase, like this:
using (SqlCommand cmd = new SqlCommand(query, _sqlserverDB))
{
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
DataSet dataSet = new DataSet();
adapter.Fill(dataSet);
result = (dataSet != null && dataSet.Tables != null && dataSet.Tables.Count > 0) ? dataSet.Tables[0] : null;
}
}
When I try to get the DataType of each column through dataColumn.DataType , I get the C# types (Int32, Int64, String, etc).
QUESTION: How can I access the native SQL data types (varchar, nvarchar, bigint...) instead of the C# types?
I have tried dataColumn.DataType.UnderlyingSystemType and the result is the same.
Of course it is possible to take SqlDbType of a column, the answer is here on SO: link.
SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = "SET FMTONLY ON; select column from table; SET FMTONLY OFF";
SqlDataReader reader = cmd.ExecuteReader();
SqlDbType type = (SqlDbType)(int)reader.GetSchemaTable().Rows[0]["ProviderType"];
You cannot because System.Data.DataTable (or DataColumn, or DataSet, or DataRow...) is a generic .NET data container which works the same way regardless on the specific database engine you loaded your data from.
this means that provided you used a .NET Connector for SQL Server, MySQL, Access, PostgreSQL or anything else, the DataTable and DataColumn classes are always the same and being ADO.NET objects are generic to work with any db engine, so the columns are typed with the .NET types as you have found out.
SqlConnection SqlCon = new SqlConnection("Data Source=(local);Database=dbname;Integrated Security=SSPI;");
SqlCon.Open();
SqlCmd = SqlCon.CreateCommand();
SqlCmd.CommandText = "select * from Tablename";
SqlDataReader SqlDr = SqlCmd.ExecuteReader();
SqlDr.Read();
int i = 0;
while (i < SqlDr.FieldCount)
{
MessageBox.Show(SqlDr.GetDataTypeName(i));
i++;
}
Another approach is to let SQL do the work for you:
SqlConnection rConn = connectToSQL(); //returns sql connection
SqlCommand SqlCmd = new SqlCommand();
SqlCmd = rConn.CreateCommand();
SqlCmd.CommandText = "SELECT ORDINAL_POSITION, " +
"COLUMN_NAME, " +
"DATA_TYPE, " +
"CHARACTER_MAXIMUM_LENGTH, " +
"IS_NULLABLE " +
"FROM INFORMATION_SCHEMA.COLUMNS " +
"WHERE TABLE_NAME = 'TableName'";
SqlDataReader SqlDr = SqlCmd.ExecuteReader();
SqlDr.Read();
while (SqlDr.Read()) {
var OrdPos = SqlDr.GetValue(0);
var ColName = SqlDr.GetValue(1);
var DataType = SqlDr.GetValue(2);
var CharMaxLen = SqlDr.GetValue(3);
var IsNullable = SqlDr.GetValue(4);
Console.WriteLine("ColName - " + ColName + " DataType - " + DataType + " CharMaxLen - " + CharMaxLen);
}
As David says ... you are in .NET so the types will be .NET types. This is a listing of type mappings from SQL Server to .Net that shows you what .NET type you will end up with for a given Sql column type .. hope this helps ..
http://msdn.microsoft.com/en-us/library/ms131092.aspx
Building upon Madhukar Krishna's answer, if you have a SQLDataReader or a MySQLDataReader object you can obtain the SQL type metadata for a given column (in the code, we obtain the metadata of column with index 1) using the following code (example working for MySQLDataReader object):
...
MySqlDataReader dr = ...
Console.WriteLine("dr.GetFieldType(1) = {0}, dr.GetName(1) = {1}, dr.GetValue(1) = {2}, dr.GetDataTypeName(1) = {3}",
dr.GetFieldType(1), dr.GetName(1), dr.GetValue(1), dr.GetDataTypeName(1));
bool b = Enum.TryParse(dr.GetDataTypeName(1), true, out System.Data.SqlDbType mySqlDbTypeEnum);
Console.WriteLine("mySqlDbTypeEnum = {0}, b = {1}", mySqlDbTypeEnum, b);
The line:
bool b = Enum.TryParse(dr.GetDataTypeName(1), true, out System.Data.SqlDbType mySqlDbTypeEnum);
is used to obtain the System.Data.SqlDbType from a String, and ignoring the letter case, e.g. if dr.GetDataTypeName(1) returns "VARCHAR" then the System.Data.SqlDbType enum value is System.Data.SqlDbType.VarChar.
Then, you can get get the size of the data type (for instance VARCHAR(15)) by inspecting the SQL columns metadata with the following code (source MSDN):
... (continuation)
DataTable schemaTable;
// Retrieve column schema into a DataTable.
schemaTable = dr.GetSchemaTable();
// For each field in the table...
foreach (DataRow myField in schemaTable.Rows)
{
// For each property of the field...
foreach (DataColumn myProperty in schemaTable.Columns)
{
// Display the field name and value.
Console.WriteLine(myProperty.ColumnName + " = " + myField[myProperty].ToString());
}
Console.WriteLine();
// Pause.
//Console.ReadLine();
}
The property ColumnSize gives the size information.
If you are using DataReader -
SqlDataReader reader = cmd.ExecuteReader();
reader.GetDataTypeName(int ordinal)
should work if you want the SQL data type of a column

Categories

Resources