Why is my SQL query for a single value failing? - c#

I have the following code that fails at the if (!rdr.Read()), and I can't see what I am doing wrong. When I look in the database using the value in fullPath, the record exists. Here's my code:
Song song = new Song();
connectionManager = new ConnectionManager();
try
{
using (SqlConnection conn = new SqlConnection(connectionManager.ConnectionString))
{
conn.Open();
string query = $"SELECT * FROM Songs WHERE FullPath LIKE '#FullPath%'";
using (SqlCommand queryString = new SqlCommand(query, conn))
{
queryString.Parameters.Add("#FullPath", SqlDbType.NVarChar, 300).Value = fullPath;
SqlDataReader rdr = queryString.ExecuteReader();
if (!rdr.Read())
{
throw new InvalidOperationException("No records were returned.");
}
song.Title = rdr["Title"].ToString();
song.Artist = rdr["Artist"].ToString();
song.Genre = rdr["Genre"].ToString();
song.Album = rdr["Album"].ToString();
song.Year = (uint)rdr["Year"];
song.Length = rdr["Length"].ToString();
song.FullPath = rdr["FullPath"].ToString();
}
conn.Close();
}
}
catch (Exception ex)
{
Logger.log.Error($"Error getting song: {fullPath}\n", ex);
}
return song;

The #FullPath placeholder for the parameter is not included in the SQL string correctly. When you use parameters, you do not put them in single-quotes. You want this:
string query = "SELECT * FROM Songs WHERE FullPath LIKE #FullPath + '%'";
Alternatively, you could do this:
string query = "SELECT * FROM Songs WHERE FullPath LIKE #FullPath";
// ...
queryString.Parameters.Add("#FullPath", SqlDbType.NVarChar, 300).Value = fullPath + "%";
Remember, parameterized queries are more than a simple sanitization + string substitution. Rather, it quarantines the data inside a variable. Therefore the SQL code must treat the placeholder as an SQL variable. What you had was just a string literal where the value happened to match the parameter name.
That's as far as I got. There may be other errors, too. If you want better help, post the actual error message.

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;
}
}

Exporting TERADATA's 'show table/view' into C# Visual Studio

I have an issue with storing teradata's query in c#.
I need to store 'show table/view' in any kind of C# data types. So far I have tried char[], var, string. No luck. It stores something but definitely not the thing I need. I'm not using the 'show ...' syntax. Just getting the DDL from dbc like this
select RequestText
from dbc.tablesv
where databasename = 'MyDatabse'
and tablename = 'MyTable';
And here is the code of my C#:
using (TdConnection cn = new TdConnection())
{
try
{
cn.ConnectionString = ConnectionStringBuilder.ConnectionString;
cn.Open();
Console.WriteLine("Connected to: " + connectionStringBuilder.DataSource);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
TdCommand cmd1 = cn.CreateCommand();
cmd1.CommandText = "select RequestText from dbc.tablesv where databasename = 'MyDatabase' and tablename = 'MyTable';";
using (TdDataReader reader1 = cmd1.ExecuteReader())
{
reader1.Read();
var RequestedText = reader1.GetString(0);
Console.WriteLine(RequestedText);
cn.Close();
Console.ReadLine();
}
}
All I get is some weird string that is not the one I get in teradata.
Moreover If I query to select any other column and store it in C# it works fine. To check the types for both columns I use this query:
select databasename, type(databasename), requesttext, type(requesttext)
from dbc.tablesv
where databasename = 'MyDatabase'
and tablename = 'MyTable';
The result is type(databasename) = varchar(128) and type(requesttext) = varchar(12500).
Thanks

SQL query return List

I can't seem to get this working:
My table column headers are 'genre' 'artist' 'album'
and the params I'm passing in are (type, filter, value) ("artist", "genre", "Rock") where there are two rows in the db with "Rock" for the genre.
When I follow the debugger, the 'while (reader.Read())' must return false because the loop is never entered and thus nothing written to the List.
public static List<String> getWithFilter(String type, String filter, String value)
{
List<String> columnData = new List<String>();
string query = "SELECT #type FROM Music WHERE" +
" #filter = '#value'";
SqlConnection connection = Database.GetConnection();
SqlCommand getData = new SqlCommand(query, connection);
getData.Parameters.AddWithValue("#type", type);
getData.Parameters.AddWithValue("#filter", filter);
getData.Parameters.AddWithValue("#value", value);
connection.Open();
using (connection)
{
using (getData)
{
using (SqlDataReader reader = getData.ExecuteReader())
{
while (reader.Read())
{
columnData.Add(reader.GetString(0));
}
}
}
}
return columnData;
}
You cannot use parameters for the names of columns and you don't put quotes around them when using them. Right now your query is the equivalent of
SELECT 'artist' FROM Music WHERE 'genre' = '#value'
You can do the following instead.
string query = "SELECT " + type + " FROM Music WHERE " + filter + " = #value";
And just remove the lines that create the #type and #fitler parameters.
You're looking either for formatting or string interpolation (requires C# 6.0):
string query =
$#"SELECT {type}
FROM Music
WHERE {filter} = #value";
...
getData.Parameters.AddWithValue("#value", value);
Formatting is a bit more wordy:
string query = String.Format(
#"SELECT {0}
FROM Music
WHERE {1} = #value", type, filter);
I assuming that you're using .net 2
DateTime current = DateTime.Now;
Console.WriteLine(current);
SqlConnection conn = new SqlConnection();
string q = "SELECT #field FROM student";
SqlDataAdapter da = new SqlDataAdapter(q, conn);
da.SelectCommand.Parameters.AddWithValue("#field", "snName");
DataTable dt = new System.Data.DataTable();
conn.Open();
da.Fill(dt);
conn.Close();
List<string> names = new List<string>();
foreach (DataRow dr in dt.Rows)
{
names.Add(dr[0].ToString());
}
Console.WriteLine("Fetching {0} data for {1}", names.Count, DateTime.Now - current);
Console.ReadKey();
You can use lambda expression to mapping the datatable in .net >4

Data Type Mismatch error in Criteria expression in Select query C# query

My sample code is as follows, I am getting following error;
Data Type Mismatch error in criteria expression.
Details => ScannerAlarmLimits is my table from .mdb database.
string jointS = dsetChamberS1.Tables[0].Rows[tot][0].ToString();
int select1S = Convert.ToInt32(jointS);
string sqlQuery1S = "SELECT TMin,TMax,HMin,HMax from ScannerAlarmLimits WHERE ScannerID='" +select1S+ "'";
OleDbCommand cmd1S = new OleDbCommand(sqlQuery1S, conn);
OleDbDataAdapter adapter1S = new OleDbDataAdapter(cmd1S);
adapter1S.Fill(dsetTempS, "ScannerAlarmLimits");
I just added single quote in the condition of where clause, now its working.
var query = "SELECT * from checkinout where read <> '1'";
If your ScannerID column is integer, then you should not use single quotes with it. Single quotes are for characters. Like;
WHERE ScannerID = " + select1S;
But as a better way, you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks. Aka bobby-tables.
And use using statement to dispose your connections, commands and adapters.
string jointS = dsetChamberS1.Tables[0].Rows[tot][0].ToString();
int select1S = Convert.ToInt32(jointS);
using(var conn = new OleDbConnection(conString))
using(var cmd1S = conn.CreateCommand())
{
cmd1S.CommandText = "SELECT TMin,TMax,HMin,HMax from ScannerAlarmLimits WHERE ScannerID = #id";
cmd1S.Parameters.AddWithValue("#id", OleDbType.Integer).Value = select1S;
using(var adapter1S = new OleDbDataAdapter(cmd1S))
{
adapter1S.Fill(dsetTempS, "ScannerAlarmLimits");
}
}

set Id equal to number contained in textbox

Hi I want to fill a combo box with names from a table where id is the number contained in textbox.The txtPartId is populated from another page as is the name in txtPart. The error I get when I run this is "Invalid column name "txtPartId"
public ReList(string Str_value, string id)//declare value
{
InitializeComponent();
txtPart.Text = Str_value;
txtPartId.Text = id.ToString();
displayRe();
}
private void displayRe()
{
try
{
sc.Open();
string Query = "select * from Re where Part_PartID =txtPartId ";
SqlCommand createCommand = new SqlCommand(Query, sc);
SqlDataReader dr = createCommand.ExecuteReader();
while (dr.Read())
{
string Name = dr.GetString(1);
cbRe.Items.Add(Name);//Displaying a list in the Combo Box
}
sc.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The quick and dirty answer is to make the following change:
string Query = "select * from Re where Part_PartID = " + txtPartId.Text;
assuming Part_PartID is an integer.
If it is a string then you can use:
string Query = string.Format("select * from Re where Part_PartID = '{0}'", txtPartId.Text);
The compiler is not going to inject the value of the text in txtPartId into your query string for you.
However, that introduces the scope for SQL injection, so I strongly suggest you parameterize your query. There are many examples of this on SO.

Categories