I want to convert DBObject value into long. I have value in db something like id = 24100001000001.
I'm using this code:
String totalcount = "SELECT MAX(id) FROM table";
SqlCommand cmd1 = new SqlCommand(totalcount, con);
cmd1.ExecuteNonQuery();
long count = (long)(cmd1.ExecuteScalar());
Using this code, I'm getting an error:
System.InvalidCastException: sSpecified cast is not valid.
at Default.method1(Object sender, EventArgs e) in c:\Users\aBhiShEkrANAa\Desktop\ABC\Prroject\Default.aspx.cs:line 43
I just want this id value into long.
Little bit simpler approach will be to use right type for the job:
var value = (long?)command.ExecuteScalar();
If you want to return default value instead of nullable:
var value = (long?)command.ExecuteScalar();
return value.GetValueOrDefault();
Nullable value will handle DbNull and using nullable will provide more information for other developers/readers.
Notice that actual value under object returned by ExecuteScalar is a long, using Convert.ToInt64 will be much overhead, because converting do much more work.
It might contain Null values. So it would be better to use Convert instead of cast in this case, or even would be better to use something like this:
var temp = cmd1.ExecuteScalar();
temp = (temp == DBNull.Value) ? null : temp;
long count = Convert.ToInt64(temp);
Related
I am trying to get value of a given table column from Ado.Net as follows
var query = "select transmission_time, actual_transaction_amount as sum_amount FROM table_name";
using (NpgsqlConnection conn = new NpgsqlConnection("connectionString"))
{
conn.Open();
NpgsqlCommand command = new NpgsqlCommand(query, conn);
using (NpgsqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var amount = reader.GetDecimal(Convert.ToInt32(reader["sum_amount"]));
result.Add(amount.ToString());//= amount;
}
}
But I get an error
System.OverflowException: Value was either too large or too small for an Int32.
Blockquote
But when I change the line to this
var amount = reader.GetDecimal(Convert.ToInt64(reader["sum_amount"]));
I get the following error
Argument 1 cannot convert from 'long' to 'int'
Please I need to convert the figures in that column to numbers and return it in my result.
The values in the column I am trying to get are like these examples
10000, 5000, 20000, etc. in a postgreSql table
The application is a Asp.Net 6 application running on Windows
Any help will be appreciated.
Thak you
This line doesn't make sense:
var amount = reader.GetDecimal(Convert.ToInt32(reader["sum_amount"]));
I assume that what you're actually trying to do there is get an int value from the sum_amount column and convert it to a decimal. What that code actually does is get a boxed int (i.e. an object reference) from the sum_amount column, unbox it and then use that int value as an index to get a decimal from a different column that probably doesn't exist. I think that what you actually meant to do was this:
var amount = Convert.ToDecimal(reader.GetInt64("sum_amount"));
I need to perform an update to a View that has multiple underlying tables using the ExecuteCommand method of a DataContext. I am using this method because of the known restriction of linqToSQL when performing this type of operation on Views having multiple underlying tables.
My existing SQL statement is similar to the following where I am setting newFieldID to a null value simply for this post to illustrate the issue. In the application, newFieldID is assigned a passed parameter and could actually be an integer value; but my question is specific to the case where the value being provided is a null type:
using (var _ctx = new MyDataContext())
{
int? newFieldID = null;
var updateCmd = "UPDATE [SomeTable] SET fieldID = " + newFieldID + "
WHERE keyID = " + someKeyID;
try
{
_ctx.ExecuteCommand(updateCmd);
_ctx.SubmitChanges();
}
catch (Exception exc)
{
// Handle the error...
}
}
This code will fail for the obvious reason that the updateCmd won't be completed in the case of a null value for the newFieldID. So how can I replace or translate the CLR null value with an SQL null to complete the statement?
I know I could move all of this to a Stored Procedure but I am looking for an answer to the existing scenario. I've tried experimenting with DBNull.Value but aside from the challenge of substituting it for the newFieldID to use in the statement, simply placing it into the string breaks the validity of the statement.
Also, enclosing it within a single quotes:
var updateCmd = "UPDATE [SomeTable] SET fieldID = '" + DBNull.Value + "'
WHERE keyID = " + someKeyID;
Will complete the statement but the value of the field is translated to an integer 0 instead of an SQL null.
So How does one go about converting a CLR null or nullable int to an SQL Null value given this situation?
Correct way to do it: use override of ExecuteCommand accepting not only command text, but also array of parameters and use parameterized query instead of command string concatenation:
var updateCmd = "UPDATE [SomeTable] SET fieldID = {0} WHERE keyID = {1}";
_ctx.ExecuteCommand(updateCmd, new [] {newFieldID, someKeyID});
It will not only prevent you from sql injection, but also it will do following for you (from MSDN description):
If any one of the parameters is null, it is converted to DBNull.Value.
Try checking newFieldID == null and change the statement accordingly.
Something like below or using separate if / else statement.
var updateCmd = "UPDATE [SomeTable] SET fieldID =" + (newFieldID == null ? "null" : Convert.ToString(newFieldID)) + " WHERE keyID = " + someKeyID;
Normally, when using Stored Procedures or Prepared Statements, you use Parameters to assign values. When you have a DbParameter, you can assign null or DBNull.Value to the Value-Property or your parameter.
If you want to have the null as text in the statement, simply use the SQL-keyword NULL
var updateCmd = "UPDATE [SomeTable] SET fieldID = NULL WHERE keyID = " + someKeyID;
As pointed out by Andy Korneyev and others, a parameterized array approach is the best and probably the more appropriate method when using Prepared statements. Since I am using LinqToSQL, the ExecuteCommand method with the second argument which takes an array of parameters would be advised but it has the following caveats to its usage.
A query parameter cannot be of type System.Nullable`1[System.Int32][] (The main issue I'm trying to resolve in this case)
All parameters must be of the same type
Shankar's answer works although it can quickly become very verbose as the number of parameters could potentially increase.
So my workaround for the problem involve somewhat of a hybrid between the use of parameters as recommended by Andy and Shankar's suggestion by creating a helper method to handle the null values which would take an SQL statement with parameter mappings and the actual parameters.
My helper method is:
private static string PrepareExecuteCommand (string sqlParameterizedCommand, object [] parameterArray)
{
int arrayIndex = 0;
foreach (var obj in parameterArray)
{
if (obj == null || Convert.IsDBNull(obj))
{
sqlParameterizedCommand = sqlParameterizedCommand.Replace("{" + arrayIndex + "}", "NULL");
}
else
sqlParameterizedCommand = sqlParameterizedCommand.Replace("{" + arrayIndex + "}", obj.ToString());
++arrayIndex;
}
return sqlParameterizedCommand;
}
So I can now execute my statement with parameters having potential null values like this:
int? newFieldID = null;
int someKeyID = 12;
var paramCmd = "UPDATE [SomeTable] SET fieldID = {0} WHERE keyID = {1}";
var newCmd = PrepareExecuteCommand(paramCmd, new object[] { newFieldID });
_ctx.ExecuteCommand(newCmd);
_ctx.SubmitChanges();
This alleviates the two previously referenced limitations of the ExecuteCommand with a parameter array. Null values get translated appropriately and the object array may varied .NET types.
I am marking Shankar's proposal as the answer since it sparked this idea but posting my solution because I think it adds a bit more flexibility.
I am using OracleDataReader.GetFieldType(i) to get the returned recordset fields of a stored procedure in order to generate a CS class file that could be used to call this SP (I need to define a property for the class for each field returned by the SP - so I need the data type of the field).
The problem is I cannot determine if the field type should be an integer or decimal, because GetFieldType(i) returns System.Decimal if the field was of type Number, so I could not determine if the field was an integer or a double/decimal value.
Here is the code I am using to get the fields returned by the SP:
#region OpenDBConnection
oConnection.ConnectionString = sDBConnectionString;
OracleCommand oCommand;
oConnection.Open();
#endregion
#region GetTheFieldsOfTheGetProcedure
oCommand = new OracleCommand("SPName", oConnection);
oCommand.CommandType = System.Data.CommandType.StoredProcedure;
foreach (Parameter oParam in oliGetProcParams)
{
OracleParameter oOracleParam = new OracleParameter();
oOracleParam.ParameterName = oParam.ParamName;
oOracleParam.Value = DBNull.Value;
oOracleParam.Direction = oParam.ParamDirection;
oOracleParam.OracleType = oParam.ParamDataType;
oCommand.Parameters.Add(oOracleParam);
}
OracleParameter oCVParam = new OracleParameter("cv_1", OracleType.Cursor);
oCVParam.Direction = System.Data.ParameterDirection.Output;
oCommand.Parameters.Add(oCVParam);
OracleDataReader oReader = oCommand.ExecuteReader();
if (oReader != null)
{
for (int i = 0; i < oReader.FieldCount; i++)
{
CustomField oField = new CustomField();
oField.Name = oReader.GetName(i);
oField.DataType = oReader.GetFieldType(i).ToString();
oliFields.Add(oField);
}
}
#endregion
oCommand.Dispose();
oReader.Dispose();
You can use DbDataReader.GetSchemaTable() to get the metadata DataTable, which contains more information about the types, including the precision and scale.
The schema table has a row for each column in the data reader, and columns like ColumnName and NumericPrecision / NumericScale. So you can walk one row after another and get all the metadata you need.
However, do note that you still need to read the value as decimal - the provider will give it to you as decimal. You should be able to map those manually to more proper types, though. Default number precisions are a bit annoying on Oracle, though, so it's quite likely you'll need to stick with decimal anyway (number(20, 0) is too big for long even though it's an integer).
I think you can do it casting the values to typeof int in a try catch, if it's not a int it should be a double.
That the approach i would try.
int value2;
using (SqlConnection dataConnection = new SqlConnection(#"Data Source=MANNAN-PC\SQLEXPRESS;Initial Catalog=WareHouse;Integrated Security=True;"))
using (SqlCommand dataCommand = new SqlCommand("Select Sum(I_Quantity) from Itemswork where I_Detail='" + maskedTextBox2.Text + "' and Order_No ='" + maskedTextBox1.Text + "'", dataConnection))
{
dataConnection.Open();
value2 = Convert.ToInt32(dataCommand.ExecuteScalar());
}
It shows the Error of DBnull because the column from which I'm getting the value is already int. I want to know what is the other way to get that value in variable's value2 definition.
Check the remarks section here:SqlCommand.ExecuteScalar Method
value2 = (Int32)dataCommand.ExecuteScalar();
As #Soner states you should be using parameterized queries to reduce the issues relating to SQL Injection etc. One of the problems you're actually experiencing is that the result being returned is NULL.
The SUM where no columns are returned is not 0, what you could do is change your output to check whether the returned value IsDbNull before trying to parse it into an integer. (See Unable to cast object of type 'System.DBNull' to type 'System.String` - although it's parsing to string the logic is the same)
ExecuteScalar will return
null if there is no result set
otherwise the first column of the first row of the resultset, which may be DBNull.
(Example modified from linked question and not syntax checked)
var tempObject = dataCommand.ExecuteScalar();
value2 = (tempObject == null || Convert.IsDBNull(tempObject) ? (int) tempObject: 0;
I have a SQL table with a column of type nvarchar(20) and want to read that column using SqlDataReader. Looks like the only way to do this is to use GetSqlChars() followed by ToSqlString():
String result = reader.GetSqlChars(index).ToSqlString().Value
the problem is that if the stored value happens to be null (and that's valid for my case) I get
[SqlNullValueException: Data is Null. This method or property cannot be called on Null values.]
System.Data.SqlTypes.SqlString.get_Value() +3212527
so I have to first check what the value returned by ToSqlString() returns in IsNull():
SqlString asSqlString = reader.GetSqlChars(index).ToSqlString();
String result = asSqlString.IsNull() ? null : asSqlString.Value;
which works but requires lots of extra code and looks really inelegant.
Is there a more elegant way to achieve the same effect?
Perhaps:
var value = reader.IsDBNull(index) ? null : reader.GetString(index);
Or even shorter:
var value = reader[index] as string;
You can use the GetValue() method:
// define your query
string query = "SELECT YourField FROM dbo.YourTable WHERE ID = 1";
using(SqlConnection conn = new SqlConnection("......"))
using(SqlCommand cmd = new SqlCommand(query, conn))
{
conn.Open();
using(SqlDataReader rdr = cmd.ExecuteReader())
{
if(rdr.Read())
{
string fieldValue = rdr.GetValue(2).ToString();
}
}
conn.Close();
}
GetString method is specifically coded to throw an exception if the database value is null. This is by design.
The docs for GetString state:
Call IsDBNull to check for null values before calling this method
On the other hand, if you use GetValue() and you end up with a DBNull object as your value, the DBNull.ToString method automatically returns String.Empty.