Imagine this code:
string value = "1.23";
string query = "UPDATE MYTABLE SET COL1=#p1";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("#p1", value);
cmd.ExecuteNonQuery();
On my database it will work with value="1.23" if COL1 is decimal type column. But it will fail if value is "1,23" (comma instead of a dot as a decimal point). The error is
Error converting data type nvarchar to numeric
I'd like it to work in both cases with "value" being a string variable.
Unfortunately I cannot just replace comma for the dot as this code is going to be more universal, dealing both with numeric and varchar columns
Is there any way that an query accepts a parameter with number written as a string both with dot and a comma and correctly puts it in into table?
Thanks for any help
If the value isn't semantically a string, you shouldn't send it as a string. The type of the parameter value is important, and influences how it is transmitted and can lead to culture issues (comma vs dot, etc).
If the value is semantically a decimal, then use something like:
string value = "1.23";
var typedValue = decimal.Parse(value); // possible specifying a culture-info
//...
cmd.Parameters.AddWithValue("#p1", typedValue);
Then it should work reliably.
Unrelated, but you can make ADO.NET a lot easier with tools like "Dapper":
connection.Execute("UPDATE MYTABLE SET COL1=#typedValue", new { typedValue });
Related
In my C# program, I use a strongly typed dataset with an access database. In one table of the DB, I use a double. With some cultures, access uses a comma instead of a point for a double value. I can read the value without a problem (IE if access uses a comma: "10,25" is read as a "10.25" double value). But when I want to insert a new value, I get an exception if access uses a comma and one of the values is a decimal (IE "10" is insert, "10.25" throw the exception). The exception is thrown when I update the DB, not when I create a new row in the dataset.
As I use a dataset, I thought that these problems were automatically handled by .Net.
How can I manage comma/point (I think I must get the culture of the user, then force the dataset to use it. But how?)?
PS : I can't change the computer culture, so I need to manage all cultures by code.
Note that doubles do not contain commas or points. They store the number in a binary representation internally using a mantissa and an exponent. The comma vs point issue only comes into play if you have a string representation of the double (most likely a sql string).
Do not write:
// Here the double is in a string
string sql = "INSERT INTO mytable (id, value) VALUES (1, 10.25)";
using (OleDbCommand cmd = new OleDbCommand(sql, conn)) {
cmd.CommandType = CommandType.Text;
conn.Open();
cmd.ExecuteNonQuery();
}
Instead use command parameters:
// Here the double is never converted to a string
string sql = "INSERT INTO mytable (id, value) VALUES (?, ?)";
using (OleDbCommand cmd = new OleDbCommand(sql, conn)) {
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("?", 1);
cmd.Parameters.AddWithValue("?", 10.25);
conn.Open();
cmd.ExecuteNonQuery();
}
Of course, in the C# code the double is written in a textual representation. However, when compiled and at runtime the double exists in its pure binary form, not remembering the character of the decimal separator used in the code.
I have a very BIG PROBLEM.
I want to delete a row from my database sql in C#.
here is my code:
int x = Convert.ToInt32(dataGridView1.SelectedCells[0].Value);
cmd.Parameters.Clear();
cmd.CommandText = "delete from Table2 where Name=#N";
cmd.Parameters.AddWithValue("#N", x);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
and finally im get a problem
Input string was not in a correct format.
Help me.
I get the error in first Line.
First problem:
dataGridView1.SelectedCells[0].Value is not a valid integer value, so Convert.ToInt32 fails.
Did you mean
string x = dataGridView1.SelectedCells[0].Value;
instead?
Second problem:
You are comparing the Name field to an integer value. I'm assuming Name is a _string_ value in the database (otherwise it's poorly named). When SQL looks for matching values, it will try to convert every value ofNamein the database to a number. if ANY value in theName` field is not a valid number, the query will fail.
I've read that null or empty string will return 0 (to be confirmed)
Here my guess :
Depending of your country, numbers should be wrote :
1.234
or
1,234
Solution
Hugly solution : You can simply do a :
Convert.ToInt32(dataGridView1.SelectedCells[0].Value.Replace(".",","));
Good solution : Or use Convert.ToInt32(String, IFormatProvider) :
Convert.ToInt32(dataGridView1.SelectedCells[0].Value,CultureInfo.CurrentCulture)
EDIT -1 without comment, i'm please to help.
I have a table I need to handle various characters. The characters include Ø, ® etc.
I have set my table to utf-8 as the default collation, all columns use table default, however when I try to insert these characters I get error: Incorrect string value: '\xEF\xBF\xBD' for column 'buyerName' at row 1
My connection string is defined as
string mySqlConn = "server="+server+";user="+username+";database="+database+";port="+port+";password="+password+";charset=utf8;";
I am at a loss as to why I am still seeing errors. Have I missed anything with either the .net connector, or with my MySQL setup?
--Edit--
My (new) C# insert statement looks like:
MySqlCommand insert = new MySqlCommand( "INSERT INTO fulfilled_Shipments_Data " +
"(amazonOrderId,merchantOrderId,shipmentId,shipmentItemId,"+
"amazonOrderItemId,merchantOrderItemId,purchaseDate,"+ ...
VALUES (#amazonOrderId,#merchantOrderId,#shipmentId,#shipmentItemId,"+
"#amazonOrderItemId,#merchantOrderItemId,#purchaseDate,"+
"paymentsDate,shipmentDate,reportingDate,buyerEmail,buyerName,"+ ...
insert.Parameters.AddWithValue("#amazonorderId",lines[0]);
insert.Parameters.AddWithValue("#merchantOrderId",lines[1]);
insert.Parameters.AddWithValue("#shipmentId",lines[2]);
insert.Parameters.AddWithValue("#shipmentItemId",lines[3]);
insert.Parameters.AddWithValue("#amazonOrderItemId",lines[4]);
insert.Parameters.AddWithValue("#merchantOrderItemId",lines[5]);
insert.Parameters.AddWithValue("#purchaseDate",lines[6]);
insert.Parameters.AddWithValue("#paymentsDate",lines[7]);
insert.ExecuteNonQuery();
Assuming that this is the correct way to use parametrized statements, it is still giving an error
"Incorrect string value: '\xEF\xBF\xBD' for column 'buyerName' at row 1"
Any other ideas?
\xEF\xBF\xBD is the UTF-8 encoding for the unicode character U+FFFD. This is a special character, also known as the "Replacement character". A quote from the wikipedia page about the special unicode characters:
The replacement character � (often a black diamond with a white question mark) is a symbol found in the Unicode standard at codepoint U+FFFD in the Specials table. It is used to indicate problems when a system is not able to decode a stream of data to a correct symbol. It is most commonly seen when a font does not contain a character, but is also seen when the data is invalid and does not match any character:
So it looks like your data source contains corrupted data. It is also possible that you try to read the data using the wrong encoding. Where do the lines come from?
If you can't fix the data, and your input indeed contains invalid characters, you could just remove the replacement characters:
lines[n] = lines[n].Replace("\xFFFD", "");
Mattmanser is right, never write a sql query by concatenating the parameters directly in the query. An example of parametrized query is:
string lastname = "Doe";
double height = 6.1;
DateTime date = new DateTime(1978,4,18);
var connection = new MySqlConnection(connStr);
try
{
connection.Open();
var command = new MySqlCommand(
"SELECT * FROM tblPerson WHERE LastName = #Name AND Height > #Height AND BirthDate < #BirthDate", connection);
command.Parameters.AddWithValue("#Name", lastname);
command.Parameters.AddWithValue("#Height", height);
command.Parameters.AddWithValue("#Name", birthDate);
MySqlDataReader reader = command.ExecuteReader();
...
}
finally
{
connection.Close();
}
To those who have a similar problem using PHP, try the function utf8_encode($string). It just works!
I have this some problem, when my website encoding is utf-u and I tried to send in form CP-1250 string (example taken by listdir dictionaries).
I think you must send string encoded like website.
I'm trying to enter a double value in an SQL update statment, which is already converted (see code 1), to keep his numbers behind the comma.
(1)
double.TryParse(splitline[8], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out natMB //conversion
(2) Putting my value in an procedure to my SQL statement, i putted natMB into 'Verbruikgegevens', index position 2. 0 or 1 indicates if my inputted data is roaming or not. This is a part of an if statement declaring weither it's roaming or national data.
sqlStatementUpdate(TrafficdataID, 0,
(Convert.ToDouble(Verbruikgegevens.Rows[intCount].ItemArray[2],
CultureInfo.InvariantCulture))
(3) SQL statement in Visual studio (C#)
public void sqlStatementUpdate(long TrafficdataID, byte Roaming, double Value)
{
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.Connection = connection2;
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.CommandText = "SP_SCTrafficdataDetailUpdate";
DataAccessHelper.AddParam(sqlCmd, "TDDValue", SqlDbType.Decimal, Convert.ToDecimal(Value));
DataAccessHelper.AddParam(sqlCmd, "TrafficdataID", SqlDbType.BigInt, TrafficdataID);
DataAccessHelper.AddParam(sqlCmd, "TDDRoaming", SqlDbType.Bit, Roaming);
DataAccessHelper.ExecSProcDS(sqlCmd);
}
(4) DataAccesHelper
internal static class DataAccessHelper
{
public static void AddParam(SqlCommand cmd, string columnName, SqlDbType dbType, object paramvalue)
{
if (paramvalue is DateTime)
{
if (((DateTime)paramvalue).Date == DateTime.MinValue.Date)
{
paramvalue = DBNull.Value;
}
}
if (paramvalue == null)
{
paramvalue = DBNull.Value;
}
string param = "#" + columnName;
if (!cmd.Parameters.Contains(param))
{
if (dbType == SqlDbType.VarChar || dbType == SqlDbType.NVarChar || dbType == SqlDbType.Char || dbType == SqlDbType.NChar)
cmd.Parameters.Add(param, dbType, 4000);
else
cmd.Parameters.Add(param, dbType);
cmd.Parameters[param].SourceColumn = columnName;
cmd.Parameters[param].Value = paramvalue;
}
}
public static DataSet ExecSProcDS(SqlCommand cmd)
{
DataSet ds = new DataSet();
try
{
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(ds);
}
catch (Exception ex)
{
throw (ex);
}
return ds;
}
(5) SQL statement
ALTER PROCEDURE [dbo].[SP_SCTrafficdataDetailUpdate] #TDDValue decimal, #TrafficdataID bigint, #TDDRoaming bit
AS
BEGIN
UPDATE TR_SCTrafficDataDetail
SET TDDValue = #TDDValue
WHERE (TDDType = 'Data') AND (TrafficDataID = #TrafficdataID) AND (TDDRoaming = #TDDRoaming)
END
QUESTION: Is it possible that I keep using a double, and also keep my numbers behind the comma when importing the data to my sqltable? Right now it doesn't seem to work that wel ... I defined my Value in my SQLTable as an decimal though
So the question is:
I have text input representing numbers, using sometimes a comma and sometimes a period for the decimal separator. How can I convert these reliably to numbers?
Answer: This has nothing to do with the SQL data types. You need to first write reliable C# code to convert the number to a double or decimal. Either will do - you should use whichever one matches your database.
The Invariant culture REQUIRES the period as a decimal point, NOT the comma. So you are using the wrong culture if you have commas as decimal separator.
If you know what format your numbers are in, use the overloaded Parse and specify the format directly.
If it is from user input, use the user's culture, OR train the user what format to use.
Finally, if you have some odd format, you might need to write your own code to regularise the format using regexes.
Speed issues
10000 rows is nothing it should take seconds not minutes.
I notice you are creating a new SqlCommand for each row. Each time you do so it has to go to the SQL server and match up the metadata with the stored proc you are calling.
Just create it once, and re-use it by setting the values to the values from the new row. Just don't forget to set the NULL ones to DBNull.Value.
How do I format the following result in currency with 2 decimal places?
string query2 = "SELECT SUM (Price) FROM Bill";
OleDbDataAdapter dAdapter2 = new OleDbDataAdapter(query2, DBconn);
DataTable source = new DataTable();
dAdapter2.Fill(source);
TotalValueLabel.Text = source.Rows[0][0].ToString();
TotalValueLabel.Text = source.Rows[0][0].ToString("c");
Some ToString overloads accepts format strings that allow you to specify the configuration of the output (this depends on class). For currency (stored in a decimal, for instance), you probably want to specify currencyValue.ToString("C") which takes the default locale into account.
Note, you may also want to pass a Locale specifier if you need results in other currencies.
See http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx for more details.