I have a string coming from a stored procedure looks like '001234567'.
sqlCommand = new SqlCommand("csp_Bbp_OBN_GetBasePageList", BBConnection);
sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
sqlCommand.Connection.Open();
// Run the SQL statement, and then get the returned rows to the DataReader.
accReader = sqlCommand.ExecuteReader();
while (accReader.Read())
{
BasePage basePage = new BasePage();
basePage.GroupNum= accReader.GetValue(0).ToString().Trim();
basePageList.Add(basePage);
accReader.Close();
accReader.Dispose();
}
return basePageList;
In my case, from the stored procedure I am returning the varchar, after executing and reading it I am getting the value to basePage.GrouNum which is a string. So, I don't see where it is trimming the leading zeros.
Example: GroupNumber in the table is : "001234567"
BasePage.GroupNum after reading from DataReader : "1234567"
But, I do not want the leading zeros being trimmed.
Can any one help me how to solve this problem?
You can convert it to an integer then format the string going out:
basePage.GroupNum = Convert.ToInt32(accReader.GetValue(0)).ToString("000000000")
Using the 0's as format specifiers should pad the result string appropriately.
If you have access to the stored procedure, make sure it returns a string. So:
select GroupNumber
instead of, for example:
select cast(GroupNumber as int) as GroupNumber
What happens if instead of
GetValue(0).ToString()
you use
GetString(0)
?
One other thing - get into the habit of wrapping things like commands and readers in using statements. You can avoid the close and dispose stuff and be assured even if your code throws you don't leave anything around.
Related
Trying to Insert into database from textboxes, but it will only accept integers and not characters - what could the problem be?
string sCMD = string.Format("INSERT INTO [Table] ([Item], [Des1],[Des2], [Prodline], [ANR], [STime]) VALUES({0},{1},'0',{2},{3},{4})"
,txtText1.Text, txtText2.Text, txText3.Text, txtText4.Text, txtText5.Text);
The name "" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
Here's something to consider:
using (SqlConnection c = new SqlConnection(connString))
{
c.Open();
using (SqlCommand cmd = new SqlCommand("INSERT INTO [Table] ([Item], [Des1],[Des2], [Prodline], [ANR], [STime]) VALUES(#Item,#Des1,'0',#ProdLine,#ANR,#STime)", c))
{
cmd.Parameters.AddWithValue("#Item", txtText1.Text);
cmd.Parameters.AddWithValue("#Des1", txtText2.Text);
cmd.Parameters.AddWithValue("#ProdLine", txText3.Text);
cmd.Parameters.AddWithValue("#ANR", txtText4.Text);
cmd.Parameters.AddWithValue("#STime", txtText5.Text);
cmd.ExecuteNonQuery();
}
}
If you were to send the SQL statement you're building to the server it might look something like this:
INSERT INTO [Table] ([Item], [Des1],[Des2], [Prodline], [ANR], [STime])
VALUES(Item Name,Here is my description.,'0',Prod line,ANR value,some time)
Clearly that's going to fail. It's not even surrounding the values with single quotes. Now, all of them may not be character, I get that, but you get my point.
But to add insult to injury it's wide open to SQL Injection the way you have it written. With the parameterized approach it's not.
This is a very dangerous line of code.
For starters, you are creating a string with no delimiters whatsoever for the values, which means that the only values that could pass withour issue are integers. Anything else needs to be delimited, which you don't do in this String.Format statement.
Worse, you are trying to create a sql statement from direct user input. Any weird value can cause your code to fail, or worse, cause execution of unwanted code. Imagine what would happen in a user entered eg 'sdf','sdfs',sdf' as the FIRST value. The resulting string would have 3 correct values for the first three columns that came from the first textboxt.
Now image what would happen if the user entered something like 'blablabla';DROP TABLE sometable;--. This would cause the Delete command to execute. This is a standard SQL injection attack scenario.
There are many more problems, eg when you try to pass numbers with floats, dates or any type whose conversion to string depends on your locale.
Instead of trying to construct a SQL query by string concatenation, you should use parameterized queries, as described in Give me parameterized SQL or give me death. The resulting code is easier to write, performs much faster, has no conversion errors and is not subject to SQL injection attacks,
I have a DateTime record in my table in a database and I write a query to get it from the database:
string command2 = "select Last_Modified from Company_Data where Company_Name='" + DescriptionEntryForm.SelectedItem.ToString() + "'";
SqlCommand search_company2 = new SqlCommand(command2, con_string.con);
SqlDataReader company_reader2 = search_company2.ExecuteReader();
dateform.Text = company_reader2.GetValue(0).ToString();
company_reader2.Close();
But the penultimate statement throw an exception saying "Invalid attempt to read when no data is present".
How can I solve it?
Well, the immediate problem with your code is that you haven't called company_reader2.Read() to move the cursor onto the first row.
From the docs for SqlDataReader.Read:
The default position of the SqlDataReader is before the first record.
Therefore, you must call Read to begin accessing any data.
You should also note the return value of Read() which indicates whether or not you've read to the end of the record set.
Other problems:
You should put using statements around the SqlCommand and SqlDataReader, otherwise if there's an exception you won't be closing the connection. You may be able to get away with disposing the command and letting the reader just disappear automatically - but I typically dispose of both just so I don't need to think too carefully.
You're assuming that the format of date/time will be appropriate by just calling ToString with no format specifier.
You should use a parameterised SQL query to avoid SQL injection attacks.
It looks like you've executed the command, but haven't actually read from it.
company_reader2 = search_company2.ExecuteReader();
if (company_reader2 != null && company_reader2.HasRows) {
company_reader2.Read();
dateform.Text = company_reader2[0].ToString();
}
i am using OleDbCommand.ExecuteNonQuery() to insert data into the database:
ObjCommand = New OleDbCommand
ObjCommand.CommandType = CommandType.StoredProcedure
ObjCommand.CommandText = StrSQL
ObjCommand.Parameters.Add("field1", OleDbType.VarChar).Value = <something1>
ObjCommand.Parameters.Add("field", OleDbType.VarChar).Value = <something2>
(...)
(...)
ObjCommand.Parameters.Add("field50", OleDbType.VarChar).Value = <something50>
ObjCommand.Connection = GetDBConnection(StrConnectionString)
ObjCommand.Connection.Open()
<some integer> = ObjCommand.ExecuteNonQuery()
And there is a conversion exception that only shows up in the last line:
error converting datatype varchar to smallint
I'd like to know if it's the normal behavior, and how do i know where the conversion problem occurs.
update:
ObjCommand.Parameters.Add("#IdMunFatoGerador", OleDbType.VarChar).Value
= ObjNFe.idMunFatoGerador
i've found this line through commenting every line and uncommenting some, this one gives me the above said exception.
ObjNFe.idMunFatoGerador is a string and gives me "error converting datatype varchar to smallint" too
That implies that one of the parameters of the query is of the wrong type. Namely you are passing varchar when you should be passing a smallint (short in c#).
Without the definition of the stored procedure there's no way we can guess which one it is..
One of the parameters you are pasing to the stored procedure as a varChar is typed in the stored procedure as an smallint. And, in this case the value you are passing in cannot be converted implicitly by the server to an integer value. Look at the stored proc definition, Either lala, or lulu is typed as an smallint. Then look at actual values you are sending it...
If you use the DataSet designer, it will generate everything for you and you'll get a compiler error instead of a run-time error. Add a new DataSet to your project then add a Query to the DataSet.
You end up with something like this:
QueriesTableAdapter ta = new QueriesTableAdapter();
ta.Connection = myConnection;
ta.MySeveralParameterStoredProc(x0, x1, ..., xN);
I guess you could loop through the parameter collection and look at the value and see if it can be numberic (string.isnumeric). The use debug.assert to output a message that the parameter value is too big to be a small int as well as the parameter name. Even better is for you to set the parameter type to be oledbtype.smallint and then only look at those. Ultimately, you need to know your parameters and how they correspond to the underlying SQL. I would just narrow my search by typing my parameters correctly and then ensure I never passed anything to the command object that wouldn't work. HTH.
Possible code:
For each parameter as SqlParameter in mycommandobject.parameters
if isnumeric(parameter.value) then
debug.assert(convert.int32(parameter.value) <= 32,767,"This parameter could have an issue - " & parameter.parametername & " value = " & parameter.value)
end if
loop
I haven't tested the code, but i believe this will work.
I've finally found it.
It was everything ok with the formats of the values.
The problem was: one of the parameters was missing. I still didn't understand it completely, but the issue was that the missing parameter (smallint) was interpreted in the following one (varchar) and so the error i found was in the second one.
In other words, field~35 was missing (haha)
So the thing is: when mounting a command to a procedure, remember to always put the fields in the exact amount and order. =)
Thank you guys!
I have a CSV file that has a column that contains strings that look like integers. That is they should be dealt with as strings, but since they are numbers they appear to be imported as integers (dropping off the leading zeroes).
Example Data:
0000000000079
0000999000012
0001002000005
0004100000007
The problem I'm seeing is that the last example data point comes through as DBNull.Value. I'm assuming this is because OleDB is treating that column as an integer (the data points come through without their leading zeroes also) and that 0004100000007 is greater than the largest integer value.
Is there some way to say "column [0] is a string, don't read it as an integer"? When reading the data?
The code I am currently using is:
OleDbConnection dbConn = new OleDbConnection(SourceConnectionString);
OleDbCommand dbCommand = new OleDbCommand("SELECT * FROM test.csv", dbConn);
dbConn.Open();
OleDbDataReader dbReader = dbCommand.ExecuteReader();
while (dbReader.Read())
{
if (dbReader[0] != DBNull.Value)
{
// do some work
}
}
Try to use GetString() method in the reader when you need to read the column as string:
string myStringValue = reader.GetString(0);
Do you have control of the export process? If so can data be exported to CSV with quotes around the string items?
If this is a one of job then just import the file into a predfined SQL table using Integration Services, but I suspect this will be a recurring task.
There's a Schema.ini file that needs to be used to specify the info about the file. It includes field types and lengths, whether there are column headers and what the field delimiter is.
Here's the MSDN Info on it.
http://msdn.microsoft.com/en-us/library/ms709353.aspx
Have you tried using this CSV reader? It is generally very respected. Perhaps give it a go...
I'm no expert but do you cope with fixed file format ?
http://csharptutorial.com/blog/exclusive-how-to-export-a-datatable-to-a-fixed-file-format-the-easy-way-using-odbc-or-jet-engine/
I'm working with a datagrid and adapter that correspond with an MSAccess table through a stored query (named "UpdatePaid", 3 paramaters as shown below) like so:
OleDbCommand odc = new OleDbCommand("UpdatePaid", connection);
OleDbParameter param;
odc.CommandType = CommandType.StoredProcedure;
param = odc.Parameters.Add("v_iid", OleDbType.Double);
param.SourceColumn = "I";
param.SourceVersion = DataRowVersion.Original;
param = odc.Parameters.Add("v_pd", OleDbType.Boolean);
param.SourceColumn = "Paid";
param.SourceVersion = DataRowVersion.Current;
param = odc.Parameters.Add("v_Projected", OleDbType.Currency);
param.SourceColumn = "ProjectedCost";
param.SourceVersion = DataRowVersion.Current;
odc.Prepare();
myAdapter.UpdateCommand = odc;
...
myAdapter.Update();
It works fine...but the really weird thing is that it didn't until I put in the odc.Prepare() call.My question is thus: Do I need to do that all the time when working with OleDb stored procs/queries? Why? I also have another project coming up where I'll have to do the same thing with a SqlDbCommand... do I have to do it with those, too?
This is called, oddly enough, a prepared statement, and they're actually really nice. Basically what happens is you either create or get a sql statement (insert, delete, update) and instead of passing actual values, you pass "?" as a place holder. This is all well and good, except what we want is our values to get passed in instead of the "?".
So we prepare the statement so instead of "?", we pass in parameters as you have above that are going to be the values that go in in place of the place holders.
Preparing parses the string to find where parameters can replace the question marks so all you have to do is enter the parameter data and execute the command.
Within oleDB, stored queries are prepared statements, so a prepare is required. I've not used stored queries with SqlDB, so I'd have to defer to the 2 answers previous.
I don't use it with SqlDbCommand. It seems as a bug to me that it's required. It should only be nice to have if you're going to call a procedure multiple times in a row. Maybe I'm wrong and there's a note in documentation about providers that love this call too much.
Are you using the JET OLEDB Provider? or MSDASQL + JET ODBC?
You should not need to call Prepare(), but I believe that's driver/provider dependent.
You definitely don't need to use Prepare() for System.Data.SqlClient.