Can't read float value from SQL Server database - c#

I use SQL Server to build my database and SqlDataReader to read data from it.
command.Connection = cn;
command.CommandText = "SELECT * FROM test";
SqlDataReader rd = command.ExecuteReader();
while(rd.Read())
{
double d = (double) rd.GetValue(0);
}
The column (0) I am trying to get value from is a 'float' type and has value '3.5' . As mapping data type from this MSDN link, the type of the object returned by rd.GetValue(0) must be 'double'. But the code above returns to variable 'd' value '0.0'. I tried this line:
double d = Convert.ToDouble(rd.GetValue(0));
But it still returns '0.0' to variable 'd'.
I tried searching on Google and StackOverflow but there is no result.
What am I missing? Help me!

As it is now, your code iterates over all the records (if there are many) an takes the last entry, which since you have no order by clause, may differ in every query execution. If indeed you want to only take 1 value, use ExecuteScalar together with an order by clause:
command.Connection = cn;
command.CommandText = "SELECT TOP 1 * FROM test order by myfield desc"; //or asc
double result = (double)command.ExecuteScalar();
Otherwise have all the result saved in a list:
...
List<double> result = new List<doulbe>();
while(rd.Read())
{
result.Add(double.Parse(rd[0].ToString());
}
Finally, if you need only the 1st field, for performance reasons, is far better not to use * but explicit set the field you want:
"SELECT TOP 1 myfield FROM test order by myfield desc"; //or asc

you can try it;
double d = (double) rd.GetValue(0);
to
double d = 0;
double.TryParse(rd["ColumnName"].ToString().Replace('.',','),out d);
OR:
double d = double.Parse(rd["ColumnName"].ToString(), CultureInfo.InvariantCulture);

This here works fine for me, im getting 3,5 in my list
List<double> columnData = new List<double>();
using (SqlConnection connection = new SqlConnection("Server=EGC25199;Initial Catalog=LegOgSpass;Integrated Security=SSPI;Application Name=SQLNCLI11.1"))
{
connection.Open();
string query = "SELECT * FROM [dbo].[floattable]";
using (SqlCommand command = new SqlCommand(query, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
columnData.Add(reader.GetDouble(0));
}
}
}
}

Oh I have found the answer. Nothing wrong with the code I wrote. The problem is that I place the breakpoint on the 'double d = (double) rd.GetValue(0)' line. That is, 'd' value is not assigned yet so that on the debug screen it returns '0.0'.
Sorry for this mistake and thank you all Stack-Over-flowers for spending your time helping me!!!!

Related

Why do i keep getting InvalidCast even though GetDouble returns a double

In a C# program with .NET framework to make a windows form I have added the following code to make a connection and to get the value of result and store in a list for later usage
public List<Info> GetInfo(string Col)
{
string connectionString = "Server=VIS-12\\TESTSQLSERVER;Database=SPCC;User Id=sa;Password=admin1234;";
string comand = $"select {Col} from Tbl_Reading where [LogTime] between '2017-07-06 14:30:26.000' and '2017-07-06 14:30:26.000' ";
using (SqlConnection conn = new SqlConnection())
{
double[] val1 = new double [100] ;
conn.ConnectionString = connectionString;
conn.Open();
SqlCommand c1 = new SqlCommand(comand, conn);
SqlDataReader reader = c1.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
int x = 0;
val1[x] = Convert.ToDouble(reader.GetDouble(0)); //this line is throwing the error
x++;
}
}
reader.Close();
List<Info> d1 = new List<Info>();
d1 = (List<Info>)val1.Cast<Info>();//ToList();
conn.Close();
return d1;
//return val1;
}
}
I still keep getting an invalid cast Exception even though the return type and the variable type is same
GetDouble does indeed return type double but there has to be a double value to get. Internally, that method will get an object reference from the specified column and cast it as type double. It is that cast that is invalid, not one that you're performing. If you look at the stack trace of the exception then you should be able to see that.
Either the column you're retrieving is the wrong data type or at least one row contains NULL in that column. If the data type is correct then you need to either filter out NULL values in your query or else account for them in your reading code.
GetDouble will throw an exception if the value internally is not a double. This will happen obviously if the column is a different type, but also if the value is a null. So you need to handle that case.
Other notes:
if (reader.HasRows) is not necessary as you can use reader.Read() to tell you the same thing.
Use a multi-line string with # to make your query more readable.
I hope Col is not coming from user-input, otherwise you have a major injection vulnerability.
You are missing using blocks to dispose your objects.
There seems to be no need for the array, just convert each value as you go along and insert into a list.
between doesn't seem to make sense here, also you should probably use a parameter for the date. If there is really a start and end time, use >= AND < rather than BETWEEN.
Consider putting the connection string in a settings file, rather than hard-coding it.
public List<Info> GetInfo(string Col)
{
string connectionString = "Server=VIS-12\\TESTSQLSERVER;Database=SPCC;User Id=sa;Password=admin1234;";
string comand = #$"
select {Col}
from Tbl_Reading
where LogTime = #time;
";
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand c1 = new SqlCommand(comand, conn))
{
c1.Parameters.Add("#time", SqlDbType.DateTime).Value = DateTime.Parse("2017-07-06 14:30:26.000");
List<Info> d1 = new List<Info>();
conn.Open();
using (SqlDataReader reader = c1.ExecuteReader())
{
while (reader.Read())
{
d1.Add((reader[0] as double) as Info);
}
return d1;
}
}

OleDB Queries not Returning All Results

What I am expecting my code to do is gather the top ten records that have an 'I' in the SQLMigrationFl field, and then process those ten records by removing that 'I' value. Below is the portion of code that handles this.
string inProgressQuery = "SELECT TOP 10 IDType, ID, Program, Date, Body,
AcctNo, ANPACAcctID, ANPACClientID, TEAMID,
ImportDate, AnnualReview, TeamGUID,
ANPACClientLastName, ANPACClientFirstName, " +
"PolicyNumber, AccountOwnerLastName,
AccountOwnerFirstName, SCRACF, SCDateTime, NoteID
FROM NoteTable WHERE SQLMigrationFl = ?";
command = new OleDbCommand(inProgressQuery, connection);
command.Parameters.AddWithValue("SQLMigrationFl", "I");
reader = command.ExecuteReader();
if(reader.HasRows)
{
while(reader.Read())
{
//clear the In Progress flag
query = "UPDATE NoteTable SET SQLMigrationFl = ? WHERE
NoteTable.NoteID = " + reader[19].ToString();
command = new OleDbCommand(query, connection);
command.Parameters.AddWithValue("SQLMigrationFl", DBNull.Value);
reader = command.ExecuteReader();
}
}
What I am finding is that the query returns one value, and processes it. Then in five seconds it finds another record and reprocesses that one. *Five seconds is just a delay we have set in code to check for more records to be processed. It processes one record at a time, rather than grabbing ten and processing those at once within the same while loop. Is something wrong with my code or query?
Thanks for the help.
The culprit is your reassigning of the data reader using reader = command.ExecuteReader();. That will now return 1 result and your next loop will be over that 1 result. Regardless for non SELECT queries use ExecuteNonQuery instead.
Other places that you can update your code to be "better" are
Use parameters whenever you have values that you want to use in your sql statements.
Always specify the type for all your parameters.
Always wrap your types instances that implement IDisposable in using blocks to ensure resources are cleaned up.
I also recommend you not share connection instances, below it seems that there might be a static connection somewhere. It would be best to not share one and create/open one when you need it and then close/dispose it.
string inProgressQuery = "SELECT TOP 10 IDType, ID, Program, Date, Body,
AcctNo, ANPACAcctID, ANPACClientID, TEAMID,
ImportDate, AnnualReview, TeamGUID,
ANPACClientLastName, ANPACClientFirstName, " +
"PolicyNumber, AccountOwnerLastName,
AccountOwnerFirstName, SCRACF, SCDateTime, NoteID
FROM NoteTable WHERE SQLMigrationFl = ?";
using(var command = new OleDbCommand(inProgressQuery, connection))
{
// I guessed on the type and length
command.Parameters.Add(new OleDbParameter("SQLMigrationFl", OleDbType.VarChar, 10)).Value = "I";
using(var reader = command.ExecuteReader())
{
while(reader.Read())
{
//clear the In Progress flag
const string UpdateQuery = "UPDATE NoteTable SET SQLMigrationFl = ? WHERE NoteTable.NoteID = ?";
using(var commandUpdate = new OleDbCommand(UpdateQuery, connection))
{
commandUpdate.Parameters.Add(new OleDbParameter("SQLMigrationFl", OleDbType.VarChar, 10)).Value = DBNull.Value;
commandUpdate.Parameters.Add(new OleDbParameter("NoteId", OleDbType.Int)).Value = reader[19];
commandUpdate.ExecuteNonQuery();
}
}
}
}

Inconsistent behavior using IDataReader.Read()

I'm running into an issue that is mind boggling to me. I've noticed that IDataReader.Read() is acting differently depending on how the IDbCommand.CommandText is set.
In the code below - If 'AID' is set and passed to EntAgencyId(), reader.Read() returns true and the program is able to enter into the while loop. If I just set 'query' in EntAgencyId() using the same value I'm passing to the function ('455'), the program is never able to enter the while loop (the same behavior happens when passing in 'AID' from a textbox.text).
public string EntAgencyId(string AID)
{
cmd = uasConnection.CreateCommand();
//query = "select * from EnterpriseAgencyTbl where AOCId = " + AID; //<--Works
query = "select * from EnterpriseAgencyTbl where AOCId = 455"; //<--Causes issue
cmd.CommandText = query;
reader = cmd.ExecuteReader();
while (reader.Read())
{
EntAgId = reader["Id"].ToString();
AgencyName = reader["Name"].ToString();
}
reader.Close();
return AgencyName;
}
When debugging, 'query' always has the same value, so why is this making a difference with .Read().
Food for thought - .Read() returns true if there are more rows; otherwise, false. In this case I tried just reading the first single row using the Item property and GetValue(), both result in an 'Object not set to an instance of an object' error.
I've completely run out of ideas, so any help will be appreciated!
If AID may come from an untrusted source, then you should really be using parameters.
Use the following code instead:
query = "select * from EnterpriseAgencyTbl where AOCId = #AOCId";
cmd.CommandText = query;
cmd.Parameters.Add(new SqlParameter("#AOCId", SqlDbType.Int) { Value = int.Parse(AID) });
Then see if this behaves the same using static inputs, such as:
cmd.Parameters.Add(new SqlParameter("#AOCId", SqlDbType.Int) { Value = 455 });
Note: I'm making the assumption, based on 'Id' in the name, that AOCId is an int type.

Problem on querystring in SQL cmd

I have the next code:
private int bla(out int itemsMin, out int purchase)
{
string ID = (Request.QueryString["Ttrsid"] ?? "0").ToString();
{
SqlConnection connection = new SqlConnection("Data Source=*****;Initial Catalog=****;User ID=****;Password=*****;Integrated Security=False;");
string commandtext = "SELECT Min FROM myItems WHERE itemId=#ID";
SqlCommand command = new SqlCommand(commandtext, connection);
connection.Open();
command.Parameters.AddWithValue("#ID", ID); //Adds the ID we got before to the SQL command
itemsMin = (int)command.ExecuteScalar();
string commandtext2 = "SELECT COUNT (*) FROM purchase";
SqlCommand command2 = new SqlCommand(commandtext2, connection);
purchase = (int)command2.ExecuteScalar();
}
return 0;
}
The code is for two labels that i use - one to get the minimum number (itemsMin), and the other is for the count of the purchase.
I'm using the querystring to get the values by the itemid that the user watching on him now.. (from the address bar (for example: items.aspx?Ttrsid=5 so i want to see the minimum number of the Ttrsid = 5).
Everything works fine. when i'm on the Ttrsid = 1 , Ttrsid = 2 - i get what i want, but when i'm enterd to the Ttrsid = 3 and so on - that's give me the error:
System.NullReferenceException
To the line:
itemsMin = (int)command.ExecuteScalar();
.. and it's not null.. the item have all the required fields like Ttrsid = 2 .... so what wrong here?
The next code is the use of the command above:
int i, p; // variable need not be initialized
Console.WriteLine(bla(out i, out p));
if (i < p)
{
haha.Visible = true;
}
else
{
haha2.Visible = true;
}
Console.WriteLine(i);
Console.WriteLine(p);
i = itemsMin , p = purchase .
I'm guessing there is no matching row in the db, so no rows returned. Sanity-check the result from ExecuteScalar - in particular, check it for null before casting to int. It is also possible that the column contains a null, but maybe I'd expect DBNull.Value for that.
Also - use using on all the IDisposable objects here; the connection and command in particular.
I assume below pasted variable is a int type variable
purchase = (int)
Hence you may not be able to convert null values to an integer so try it changing the sql command as below
SELECT isNull(COUNT (*),0) FROM purchase
#Marc I'm really sorry about it
Don't you want to specify a column name next to the min statement? As below
SELECT Min(columnName) FROM myItems WHERE itemId=#ID ?

Getting MySQL record count with C#

I would like to know how can I get record count of a query with C#.
Here is the code that I use..
MySqlDataReader recordset = null;
query = new MySqlCommand("SELECT * FROM test ORDER BY type_ID ASC", this.conn);
recordset = query.ExecuteReader();
while (recordset.Read())
{
result.Add(recordset["type_ID"].ToString());
}
return result;
I was using a SELECT COUNT(*) and expected an int to be returned. You may need this to get a usable value:
mysqlint = int.Parse(query.ExecuteScalar().ToString());
A couple of things...
The SQL statement you would use is:
SELECT COUNT(*) FROM test
However, when using the MySQL Connector/Net to connect to MySQL through C# there is some care to be given when handling query results.
For example, as cited in this question and on Microsoft Connect int.Parse("0") equivalently known as Int32.Parse("0") can throw a FormatException on some machines.
I have found that Convert.ToInt32 handles this case nicely.
So your code will be something like this:
using (var conn = new MySqlConnection(cs))
{
conn.Open();
using (var cmd = new MySqlCommand("SELECT COUNT(*) FROM test", conn))
{
int count = Convert.ToInt32(cmd.ExecuteScalar());
return count;
}
}
Remember to make use of using statements in order to ensure that the MySQL objects get disposed of properly.
You're adding a new element in result for each row. Depending on the type of result you should be able to do something like result.Count after the while loop completes.
You could run another query first to get the count :
query = new MySqlCommand("SELECT count(*) as theCount FROM test ORDER BY type_ID ASC", this.conn);
but in truth, you are probably best changing the problem so you wont need the count until after you have populated the list.

Categories

Resources