SELECT query on Nvarchar column returning Int - c#

I'm trying to return a string value from my database but instead the query is returning "0" although the SELECT query is targeting a nvarchar column.
The query is valid and runs correctly, returning "KYO" when run using SQL-SMS.
This is the method, which works as expected in the other place I use it, that I use for returning data:
public static object GetData(string sql, SqlParameter[] parameters)
{
try
{
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString;
using (DbCommand command = factory.CreateCommand())
{
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = sql;
if (parameters != null)
{
foreach (var parameter in parameters)
{
if (parameter != null)
command.Parameters.Add(parameter);
}
}
object result = null;
SqlParameter returnValue = new SqlParameter("ReturnValue", result);
returnValue.Direction = ParameterDirection.ReturnValue;
command.Parameters.Add(returnValue);
connection.Open();
command.ExecuteScalar();
result = command.Parameters["ReturnValue"].Value;
return result;
}
}
}
catch (Exception)
{
throw;
}
}
}
This is the method which is throwing a cast exception as it's returning an int instead of a string:
private static String GetManufacturerCode(Int32 manufacturerID)
{
try
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT ManufacturerCode FROM Manufacturers WHERE ManufacturerID = #ID");
SqlParameter id = new SqlParameter("#ID", manufacturerID);
return(String)DB.GetData(sql.ToString(), new[] { id });
}
catch (Exception)
{
throw;
}
}
I also set returnValue.DbType = DbType.String; as a test and this still returned an integer.
An example of where I use the GetData(...) method successfully is:
public static Int32 GetMonitoredCount()
{
try
{
String GetMonitoredCount = "SELECT COUNT(*) FROM Devices WHERE Monitored = 1 ";
return (Int32)DB.GetData(GetMonitoredCount, null);
}
catch (Exception)
{
throw;
}
}
I considered it might be returning a boolean bit but as my query executes correctly I'd have assumed it would return 1 not 0.
Why is an integer being returned? How can I return a string using my pattern?

ReturnValue always returns int - this is by design.
Instead of this entire block
object result = null;
SqlParameter returnValue = new SqlParameter("ReturnValue", result);
returnValue.Direction = ParameterDirection.ReturnValue;
command.Parameters.Add(returnValue);
connection.Open();
command.ExecuteScalar();
result = command.Parameters["ReturnValue"].Value;
Try
connection.Open();
object result = command.ExecuteScalar();
This will return you real result of your SQL statement
Method ExecuteScalar itself is capable of returning value - it return first column of the first row of the resultset and is ideal when your query returns a single value.

Related

If the SELECT SQL Server value is null, the query takes 5 minutes C #

I have a very silly problem. I am doing a select, and I want that when the value comes null, return an empty string. When there is value in sql query, the query occurs all ok, but if there is nothing in the query, I have to give a sqlCommand.CommandTimeout greater than 300, and yet sometimes gives timeout. Have a solution for this?
public string TesteMetodo(string codPess)
{
var vp = new Classe.validaPessoa();
string _connection = vp.conString();
string query = String.Format("SELECT COUNT(*) FROM teste cliente WHERE cod_pess = {0}", codPess);
try
{
using (var conn = new SqlConnection(_connection))
{
conn.Open();
using (var cmd = new SqlCommand(query, conn))
{
SqlDataReader dr = cmd.ExecuteReader();
if(dr.HasRows)
return "";
return codPess;
}
}
}
You should probably validate in the UI and pass an integer.
You can combine the usings to a single block. A bit easier to read with fewer indents.
Always use parameters to make the query easier to write and avoid Sql Injection. I had to guess at the SqlDbType so, check your database for the actual type.
Don't open the connection until directly before the .Execute. Since you are only retrieving a single value you can use .ExecuteScalar. .ExecuteScalar returns an Object so must be converted to int.
public string TesteMetodo(string codPess)
{
int codPessNum = 0;
if (!Int32.TryParse(codPess, out codPessNum))
return "codPess is not a number";
var vp = new Classe.validaPessoa();
try
{
using (var conn = new SqlConnection(vp.conString))
using (var cmd = new SqlCommand("SELECT COUNT(*) FROM teste cliente WHERE cod_pess = #cod_pess", conn))
{
cmd.Parameters.Add("#cod_pess", SqlDbType.Int).Value = codPessNum;
conn.Open();
int count = (int)cmd.ExecuteScalar();
if (count > 0)
return "";
return codPess;
}
}
catch (Exception ex)
{
return ex.Message;
}
}

commandtext parameter changes type when executing

I have a problem in my c# application, when executing a commandtext on an ms-sql-server. Here is the function i use:
public T ExecuteScalar<T>(string commandText, IDbDataParameter[] parameters)
{
T result_value = default(T);
using (var connection = this.CreateConnection())
{
connection.Open();
using (var transaction = connection.BeginTransaction(IsolationLevel.ReadUncommitted))
{
using (var command = connection.CreateCommand())
{
command.Transaction = transaction;
command.CommandText = commandText;
command.CommandTimeout = this.CommandTimeOut;
if (parameters != null)
{
foreach (var parameter in parameters)
{
command.Parameters.Add(parameter);
}
}
object result = command.ExecuteScalar(); //Error is thrown here!
if (result is DBNull || result == null)
{
result_value = default(T);
}
else
{
Type type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
if (type.IsEnum)
{
if (Enum.IsDefined(type, Int32.Parse(result.ToString())))
{
result_value =(T)Enum.Parse(type, result.ToString());
}
}
else
{
result_value = (T)Convert.ChangeType(result, type);
}
}
}
transaction.Commit();
}
}
return result_value;
}
The commandtext looks like this:
"insert into tbl_Person (Vorname,Nachname,Strasse,HausNr,PLZ,Ort) output inserted.id values (#Vorname,#Nachname,#Strasse,#HausNr,#PLZ,#Ort)"
Inspecting the parameters-property of my commandtext-object states out, that the HausNr-parameter has the following values:
db-type: string
sql-db-type: NVarChar
sql-value: {13/5}
value: "13/5"
So the HausNr-parameter should be a string right? But when executing the command, the following error is thrown:
"Fehler beim Konvertieren des nvarchar-Werts \"15/3\" in den
int-Datentyp."
Failed to convert the nvarchar-value \"15/3\" to the int-datatype
This looks like he is trying to convert the HausNr-parameter-value to an integer-value. Why does this happen?
The error message says that the database driver tries to convert yout string value to an integer value. The reason is that the column HausNr is an integer in your database.
So double check your database schema and change HausNr to an NVarChar.

C# ExecuteReader has rows but result view initially with question marks

ExecuteReader has rows but initially when i hover and look at result view it has question marks for all the rows. Then when i go back in a second time to hover it says enumeration yielded no results. the HasRows is true however. I'm also getting my output parameters fine, but not the result set from the select statement. I'm executing a sql server stored proc. the SP executes fine in management studio. And again i am getting the output parms, just not the result set.
internal static CrossWalk Create(string senderId, string ediType)
{
var connection = ConfigurationManager.ConnectionStrings["caeCustom"];
DbCommand cmd = new SqlCommand();
cmd.CommandText = "emb_edi_xwalk_select";
cmd.CommandType = CommandType.StoredProcedure;
cmd.AddParameter("#pSENDER_ID", senderId);
cmd.AddParameter("#pMAPPING_TYPE", ediType);
var delegateId = new SqlParameter
{
ParameterName = "#pDELEGATE_ID",
SqlDbType = SqlDbType.Int,
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(delegateId);
var crossWalk = new CrossWalk();
var dbFactory = DbProviderFactories.GetFactory(connection.ProviderName);
using(var sqlConnection =
dbFactory.CreateConnection(connection.ConnectionString))
{
cmd.Connection = sqlConnection;
using (var sqlReader = cmd.ExecuteReader())
{
if (sqlReader.HasRows)
{
while (sqlReader.Read())
{
//Mapping of AAA values will be AAA03~internal_value -->
loop~external_value
//i.e. AAA03~1008 --> 2010EA~51
string key;
string value;
if (sqlReader["element"].ToString() == "AAA03")
{
key = string.Join("~",
sqlReader["element"].ToString(), sqlReader["internal_value"].ToString());
value = string.Join("~", sqlReader["loop"].ToString(),
sqlReader["external_value"].ToString());
}
else
//Normal xwalk mapping will be loop+element~external_value
--> internal_value
//i.e. 2010ANM101~X3 --> 3
{
key = string.Join("~", sqlReader["loop"] +
sqlReader["element"].ToString(), sqlReader["external_value"].ToString());
value = sqlReader["internal_value"].ToString();
}
crossWalk._lookups.Add(key, value);
}
}
sqlReader.Close();
}
crossWalk.DelegateId =
Convert.ToInt32(cmd.Parameters["#pDELEGATE_ID"].Value);
}
return crossWalk;
}

Return a string from a method that uses a method as a parameter

I have a SQL template method that I want to return a string as well as a variety of methods that execute queries that I want to get the string from:
private string sqlQueryReturnString(Action<SqlConnection> sqlMethod)
{
string result = "";
SqlConnection conn = new SqlConnection();
conn.ConnectionString = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
try
{
//open SQL connection
conn.Open();
result = sqlMethod(conn);
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex.ToString());
}
finally
{
conn.Close();
}
return result;
}
//Get the primary key of the currently logged in user
private string getPKofUserLoggedIn(SqlConnection conn)
{
int result = 0;
SqlCommand getPKofUserLoggedIn = new SqlCommand("SELECT [PK_User] FROM [User] WHERE [LoginName] = #userIdParam", conn);
//create and assign parameters
getPKofUserLoggedIn.Parameters.AddWithValue("#userIdParam", User.Identity.Name);
//execute command and retrieve primary key from the above insert and assign to variable
result = (int)getPKofUserLoggedIn.ExecuteScalar();
return result.ToString();
}
Above is how I would think this is approached. THis would be the call:
string test = sqlQueryReturnString(getPKofUserLoggedIn);
THis part is not working:
result = sqlMethod(conn);
It appears sqlMethod is presumed void.
What do I do to get the functionality I want?
You want a Func<SqlConnection, string>. Action is for void methods, Func for methods that return something.

Int Result Doesnt Increment using Cmd.ExecuteScalar PRoblem?

Now this is my Code on Updating Records.
Data Access:
public int UpdateBatch(FillinEntity fin)
{
int result = 0;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand dCmd = new SqlCommand("UpdatebyBatch", conn))
{
dCmd.CommandType = CommandType.StoredProcedure;
try
{
dCmd.Parameters.AddWithValue("#Batch", fin.Batch);
dCmd.Parameters.Add("#Date", SqlDbType.DateTime).Value = DateTime.Now.ToString();
dCmd.Parameters.AddWithValue("#User", fin.ModifiedBy);
result = Convert.ToInt32(dCmd.ExecuteScalar());
return result;
}
catch (SqlException ee)
{
throw ee;
}
finally
{
if (conn.State == ConnectionState.Open) conn.Close();
}
}
}
}
BUSINESS LOGIC:
public int UpdateBatch(FillinEntity fin)
{
DAL pDAL = new DAL();
try
{
return pDAL.UpdateBatch(fin);
}
catch
{
throw;
}
finally
{
pDAL = null;
}
}
UI:
FillinEntity fin = new FillinEntity();
BAL pBAL = new BAL();
try
{
fin.Batch = txtBACTHCODE.Text.Trim();
fin.ModifiedBy = lblUser.Text;
int result = pBAL.UpdateBatch(fin);
if (result > 0)
{
MessageBox.Show("Make Sure Batch is All Kitted!");
}
else
{
MessageBox.Show("Record Updated Successfully.");
}
SQL:
UPDATE dbo.FG_FILLIN SET
Status='SHIPPED'
,DateModified=#Date
,ModifiedBy=#User
WHERE Batch = #Batch and (Status='KITTED')
My Problem is It always return 0 result so my Message Box always Prompt Successfull even my Status is NOT KITTED.
Thanks in Regards!
Your stored procedure isn't returning a value thatExecuteScalar can make use of. You can use the ExecuteNonQuery method instead to return the number of affected records.
result = dCmd.ExecuteNonQuery();
In order for ExecuteScalar to return a value, you have to return one. You can modify your SQL to look like this:
UPDATE dbo.FG_FILLIN SET
Status='SHIPPED'
,DateModified=#Date
,ModifiedBy=#User
WHERE Batch = #Batch and (Status='KITTED')
SELECT ##ROWCOUNT
or you can use the ExecuteNonQuery method instead.

Categories