I am fetching a column from database of char(2) data type.
On an Event, I am changing the char data type to int and incrementing it by 1, with this code:
int i = 0;
using (SqlConnection sqlCon = new SqlConnection(Login.connectionString))
{
string commandString = "SELECT MAX(CAST(Category_Code as INT)) FROM Category;";
SqlCommand sqlCmd = new SqlCommand(commandString, sqlCon);
sqlCon.Open();
SqlDataReader dr = sqlCmd.ExecuteReader();
while (dr.Read())
{
i = 1;
if (dr[0] == null)
{
Ctgry_CtgryCodeCb.Text = "1";
}
else
{
int cat_next_code = int.Parse(dr[0].ToString());
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
}
}
}
It is working properly but not for the first time (doesn't add 1 to empty or 0) as column is empty.It shows some error that it is not is correct format to convert. I also set the default value of the column to 0, but it shows ((0)) as default value.
Any help would be appreciated.
If you are using this code to increment primary key value of the database table, you shouldn't be doing this way. You should be using IDENTITY column feature available in the database.
Since you have not explained why you are not using IDENTITY column, looks like this code is for some other purpose.
As per your code you are getting Maximum value of some column from the database and incrementing it by one in the code.
When the table in the database is empty you not get anything is the reader. So While loop will not be executed at all. So even if you are checking for NullOrEmpty inside the while loop, it will never get executed.
Also you don't need to use SqlDataReader here. Since you are returning only one single value from the query you can use ExecuteScalar method of SqlCommand and get that value. It will be simpler.
var codeFromDb = sqlCmd.ExecuteScalar();
var cat_next_code = 0;
if(!(codeFromDb is DBNull))
{
cat_next_code = Convert.ToInt32(codeFromDb);
}
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
My strong recommendation is to use IDENTITY column instead of doing all this code.
This will help you resolve your current issue.
SqlDataReader is overkill in this case and I don't like to answer for the wrong approach but since you insist consider following.
SqlDataReader dr = sqlCmd.ExecuteReader();
int cat_next_code = 0;
if(dr.Read()) // while is not needed here. There will be only one row in the reader as per the query.
{
i = 1;
if(!dr.IsDBNull(0))
{
cat_next_code = int.Parse(dr[0].ToString());
}
}
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
Related
I seem to be having problems with my method that will return an Integer. I am attempting to modify the rows of a particular column with this returning Integer. The database will update the pre-existing column values with this new returned value. However, it appears that every row is being modified to the LAST row's value, regardless of what the specific row held previously. I am sure my code is just overwriting the variable, but I am wondering where. Here is my method; would appreciate feedback.
private int extractValue()
{
if (connection.State != ConnectionState.Open)
{
this.connection.Open();
}
ParsingHelper helper = null // different class - no issues with this.
String query = "SELECT device FROM dLogger";
OdbcCommand command = new OdbcCommand(query, this.connection);
List<Int32> list = new List<Int32>();
OdbcDataReader reader = null;
reader = command.ExecuteReader();
while (reader.Read())
{
list.Add(reader.GetInt32(0));
for (int i = 0; i < reader.FieldCount; i++)
{
helper = new ParsingHelper();
helper.assemble(list[i]);
}
}
return helper.getFirst();
}
No problem with the ParsingHelper here, it does the correct work. My problem is the overwriting. I thought a List would alleviate this issue but I am missing something, evidently.
EDIT: Would this approach work better?
while(reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
list.Add(reader.GetInt32(i));
//....
}
If my table originally looked like this:
ColA
1
2
3
4
And my function, for example, multiplied each number by 2. The new column would look like
ColA
8 // rather than 2
8 // rather than 4
8 // rather than 6
8 // 8 is the last value - therefore, correct.
So you see, I am running into some overwriting issues here. It appears the reader will read effectively and to the last row but it is not modifying values correctly, it is only assigning each value to the last value.
EDIT:
Here is where I am updating my database:
private void update()
{
String query = "UPDATE dLogger SET device = ?";
OdbcCommand command = new OdbcCommand(query, this.connection);
if (this.connection.State != ConnectionState.Open)
{
this.connection.Open();
}
command.Parameters.AddWithValue("?", extractValue());
}
Also, here is my simple Parsing Helper Class assemble()
private void assemble(int value)
{
setFirst(value);
}
private void setFirst(int value)
{
value = value * 2;
}
Just change your
String query = "SELECT device FROM dLogger";
to
String query = "UPDATE dLogger SET device=device*2";
thus:
private void extractValue()
{
if (connection.State != ConnectionState.Open)
{
this.connection.Open();
}
String query = "UPDATE dLogger SET device=device*2";
OdbcCommand command = new OdbcCommand(query, this.connection);
command.Execute();
}
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.
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();
I am trying to determine if a specific value exists in a Oracle database table.
I used a query with "select count(*)", "select count(1)" and select count(<col_name>)" but keep getting the wrong result. When I use SQL Developer and run the query I get zero for the count. However, in the DAL, I get 1. I am guessing it is returning the number of row rather than the count itself. I tried both executeScalar() and ExecuteReader().
public override bool zipExists(string sZipCode)
{
OracleConnection conn = new OracleConnection(this.OraDataConnectionString);
OracleCommand oraCmd = new OracleCommand();
decimal iNumEntries = 0;
string sQuery = "select count(ZIPCODEID) as ZipCount from ZIPCODE where ZIPCODE = :ZipCode";
SetOraCommandType(oraCmd, CommandType.Text, sQuery);
conn.Open();
oraCmd.Connection = conn;
oraCmd.BindByName = true;
AddParamToOraCmd(oraCmd, "ZipCode", OracleDbType.Varchar2, 11, ParameterDirection.Input, sZipCode);
using (OracleConnection cn = new OracleConnection(this.OraDataConnectionString))
{
oraCmd.Connection = cn;
cn.Open();
iNumEntries = (decimal)oraCmd.ExecuteScalar();
}
return iNumEntries > 0;
also tried:
OracleDataReader sqlReader = oraCmd.ExecuteReader();
try
{
if (sqlReader.Read())
{
if (sqlReader["ZipCount"] != DBNull.Value)
iNumEntries = Convert.ToInt16(sqlReader["ZipCount"]);
}
}
}
return iNumEntries > 0;
I try you code on my table but pointing to some column and giving a select count(EN_Qty) as ZipCount from PSLAT.FSDEV.dbo.PS_EN_GEN_INTFC_BI where EN_Qty = '2600' works on my end so where in the code exactly are you experiencing an issue..? fyi I replaced my table with your query and assigned a value to the where clause.. so you query looks right.. however I would do an order by query to see if you perhaps are missing a zipcode..also oraCmd.ExecuteScalar() returns only 1 row so make sure you are not returning more than one row..oracle is funny like that
change your code to the following
object bExists = oraCmd.ExecuteScalar();
var bexists = bExists != DBNull.Value && result != null;
or change your code to check for row.count > 0 if true then you know the zipcode was found. Remember when making changes to Sql scripts or stored procedures in Oracle, you need to Compile the changes otherwise the changes will be visible to you when looking at the code but not to the caller trying to execute the stored proc.
Here is my code in C#:
float r_discountValue = 0;
SqlConnection con = Constant.GetConnection();
SqlCommand cmd = new SqlCommand("Coupon_GetDiscountFromValidCouponCode", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#PKCouponCode", SqlDbType.VarChar);
cmd.Parameters["#PKCouponCode"].Value = "DIS_77";
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
if(reader.Read()){
r_discountValue = float.Parse(reader[0].ToString());
}
reader.Close();
}
catch(Exception exception)
{
throw exception;
}
finally{
con.Close();
}
return r_discountValue;
The stored procedure:
ALTER PROCEDURE [dbo].[Coupon_GetDiscountFromValidCouponCode]
#PKCouponCode varchar(50)
AS
SELECT *
FROM Coupon
WHERE CouponCode = #PKCouponCode AND Valid = 1
Here is how the DB looks like:
I encounter an error
Input string was not in a correct format
I don't know what's thing is going wrong, any ideas?
If you want the discount value, then you should return only the discount from the SP (since it is named GetDiscountfrom...)
SELECT CouponDiscount FROM Coupon WHERE CouponCode = #PKCouponCode AND Valid = 1
This will make it a one-column resultset, which matches the access reader[0] from C#.
The other option is of course to change the C# side to read the second item (index 1) or reference the column by name, e.g.
r_discountValue = float.Parse(reader[1].ToString());
r_discountValue = float.Parse(reader["CouponDiscount"].ToString());
You would have got Input string was not in a correct format. because it was reading "DIS_77" which float.parse cannot process.
You are using first column i.e.CouponCode for fetching discount. instead of that you need to use second column ie. couponDiscount
So try something like this
r_discountValue = float.Parse(reader["CouponDiscount"].ToString());