C# select SQL query with parameter - c#

I would like to migrate database from MS Access to SQL Server and I'm trying to modify my SQL queries. In MS Access they worked.
I have this C# code:
private DataSet GetIncident_ByIncident(string inc_num)
{
MainIncident mi = new MainIncident();
mi.incident_full_number = inc_num;
string query = #"SELECT MainIncidentTable.Incident_Full_Num ,
MainIncidentTable.Customer_Name ,
MainIncidentTable.Service_Representative ,
MainIncidentTable.Incident_Date ,
MainIncidentTable.Average_Invoice ,
MainIncidentTable.Street ,
MainIncidentTable.City ,
MainIncidentTable.Contact ,
IncidentStatuses.Incident_Status_Name,
Stations.Station_Name
FROM(MainIncidentTable INNER JOIN
Stations ON MainIncidentTable.Current_Station_ID = Stations.Station_ID)
INNER JOIN IncidentStatuses ON MainIncidentTable.Current_Incident_Status_Id = IncidentStatuses.Incident_Status_Id
WHERE Incident_Full_Num = '#Incident_Full_Num'";
List<OleDbParameter> l = new List<OleDbParameter>();
l.Add(new OleDbParameter("#Incident_Full_Num", mi.incident_full_number));
l.Add(new OleDbParameter("#Customer_Name", mi.customer_name));
l.Add(new OleDbParameter("#Service_Representative", mi.service_representative));
l.Add(new OleDbParameter("#Incident_Date", mi.incident_date));
l.Add(new OleDbParameter("#Average_Invoice", mi.average_invoice));
l.Add(new OleDbParameter("#Street", mi.street));
l.Add(new OleDbParameter("#City", mi.city));
l.Add(new OleDbParameter("#Contact", mi.contact));
l.Add(new OleDbParameter("#Current_Station_ID", mi.current_station_id));
l.Add(new OleDbParameter("#Current_Incident_Status_Id", mi.current_incident_status_id));
var con = GetDataSetWithParameters(query, l);
return con;
}
Connection method :
public static DataSet GetDataSetWithParameters(string query, List<OleDbParameter> parameters)
{
DataSet ds = new DataSet();
OleDbConnection Con = new OleDbConnection(sqlConnectionString);
Con.Open();
try
{
using (OleDbCommand cmd = new OleDbCommand(query, Con))
{
if (parameters != null)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
using (OleDbDataAdapter Adapter = new OleDbDataAdapter(cmd))
{
Adapter.Fill(ds);
}
return ds;
}
}
catch
{
throw;
}
finally
{
CloseConnection(ref Con);
}
}
SQL query is working but not returning rows. I guess that problem is a syntax of parameter in query.
Can someone direct me?

You must not enclose your parameters in quotes. The library will take care of that. Ie use
WHERE Incident_Full_Num = #Incident_Full_Num
instead of
WHERE Incident_Full_Num = '#Incident_Full_Num'
EDIT
Oh sorry, forgot, that OleDb doesn't use named parameters but only positional parameters. See docs
So either update your query to
WHERE Incident_Full_Num = ?
or you use SqlCommand and SqlParameter instead of OleDbCommand and OleDbParameter.
Be aware, that if you use OleDbCommand the order in which you pass the parameters is important. Ie, the first ? will be bound to the first parameter, the second ? to the second parameter and so on. If you need the same parameter in your query twice, you would also need to pass it twice.
Furthermore it seems, only the first parameter is used. Why are you passing numerous unused parameters to your command?

Related

Stored procedure returns no rows with SqlDataAdapter

I'm new to using SqlDataAdpter and I'm trying to execute a stored procedure. The stored procedure executes successfully but no rows are returned. I've used SQL Server Profiler to monitor the call and it runs successfully (I can copy and execute the query from profiler without modifying it and get results).
I have the following:
public ActionResult Index()
{
SqlConnection conn = null;
DataSet results = null;
try
{
string connectionString = // ... my connection
conn = new SqlConnection(connectionString );
string query = #"usp_mySP";
conn.Open();
SqlDataAdapter sqlAdpt = new SqlDataAdapter(query, conn);
sqlAdpt.SelectCommand.CommandType = CommandType.StoredProcedure;
var dataDate = new SqlParameter { ParameterName = "#DataDate", Value = DateTime.Now };
var idList = new SqlParameter { ParameterName = "#IDList", Value = "1231,2324,0833" };
sqlAdpt.SelectCommand.Parameters.Add(dataDate);
sqlAdpt.SelectCommand.Parameters.Add(idList);
results = new DataSet();
sqlAdpt.Fill(results);
sqlAdpt.Dispose();
}
catch (SqlException e)
{
throw new Exception("Exception:" + e.Message);
}
finally
{
if (conn != null)
conn.Close();
}
return View(results);
}
When I inspect the DataSet through the debugger, it always returns 0 rows.
Please help with what I'm doing wrong?
Note: I've also tried (but do NOT prefer) executing as a SQL command:
EXEC usp_mySP #DataDate, #IDList
and it didn't work either as I got int to varchar conversion errors.
I think you try to add SqlParameter using SqlCommand like this :
SqlCommand cmd = new SqlCommand();
cmd.parameter.addwithvalue(#DataDate,DateTime.Now);
So the reason was because of set nocount on. I added it to my sp and it works. Thank you everyone for clarifying.

How to get the result of an "EXEC storedProcedure()" in C#

Don't ask me why, but I want put in an sqlCommand object something like this:
sqlConnection a = new sqlConection(...);
sqlCommand b = new sqlCommand("EXEC storedProcedure()", a);
sqlDataAdapter c = new sqlDataAdapter(b);
DataTable d = new DataTable();
c.Fill(d);
So, when the stored procedure makes an insert the row is successfully added but however the code throws an Exception.
I know exist an sqlCommand.CommandType specifically for stored procedures but my architecture need it made in this way.
set the adapter "SelectCommand" property instead
var cmd = new SqlCommand("EXEC storedProcedure()", a);
cmd.CommandType = CommandType.StoredProcedure; //set command property
//..
var adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd; //set adapter command for select query
and your command type must be CommandType.StoredProcedure to exec SP and your architecture don't need this? simply ask him for a good reason.
Your SQL syntax is off.
From http://technet.microsoft.com/en-us/library/ms188332.aspx :
USE AdventureWorks2012;
GO
DECLARE #CheckDate datetime;
SET #CheckDate = GETDATE();
EXEC dbo.uspGetWhereUsedProductID 819, #CheckDate;
GO
So your code should be:
new sqlCommand("EXEC storedProcedure", a);
While there are many ways to do the same thing, there are some things that work best when you do them the way the framework suggests.
In this case there are several things that can happen when you run the stored procedure, depending on which procedure it is. It might return a set of row, or several sets of rows, or nothing at all. There are already things we can do to handle all those situations, courtesy of the .NET framework.
Here's some extension code I've used in the past for any SP that is returning one or more rowsets:
public static DataSet ExecuteStoredProcedure(this SqlConnection connection, string SPName, params object[] parameters)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = SPName;
cmd.CommandTimeout = 60;
if (connection.State != ConnectionState.Open)
connection.Open();
SqlCommandBuilder.DeriveParameters(cmd);
int index = 1;
foreach (object p in parameters)
{
if (index >= cmd.Parameters.Count)
break;
cmd.Parameters[index++].Value = (p == null ? DBNull.Value : p);
}
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
DataSet res = new DataSet();
adapter.Fill(res);
return res;
}
}
}
Handling non-rowset return values and output parameters takes a bit more work, but this will do for your immediate needs:
var conn = new SqlConnection("some connection string");
DataSet ds = conn.ExecuteStoredProcedure("storedProcedure");
DataTable d = ds == null ? null : ds.Tables.Length < 1 ? null : ds.Tables[0];

Query & generic

I'm developing a C# solution with data access to Oracle.
And would like to have a generic solution about query.
Here is a part of my code :
public DataTable GetData(string query)
{
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OracleClient");
using (DbConnection conn = factory.CreateConnection())
{
try
{
DbConnectionStringBuilder csb = factory.CreateConnectionStringBuilder();
csb["Data Source"] = #"Northwind";
csb["User Id"] = #"Northwind";
csb["Password"] = #"Northwind";
conn.ConnectionString = csb.ConnectionString;
conn.Open();
using (DbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = query;
using (DataTable dt = new DataTable())
{
DbDataAdapter da = factory.CreateDataAdapter();
cmd.CommandType = CommandType.Text;
da.SelectCommand = cmd;
da.Fill(dt);
return dt;
}
}
}
catch (Exception ex)
{
throw new Exception("Error", ex);
}
finally
{
if (conn.State != ConnectionState.Closed)
conn.Close();
}
}
}
And I call my method like this :
DataAccess.Provider data = new DataAccess.Provider();
DataTabel dt = dt.GetData("select * from myTable);
This works pretty good but this is not my aim.
I have a second class called CL_mpg with all my SQL queries.
class CL_MPG
{
public string rq_sql;
public string selectParam(string param)
{
this.rq_sql = "select * from myTable where id = '" + param + "';";
return this.rq_sql;
}
public string select()
{
this.rq_sql = "select * from myTable";
return this.rq_sql;
}
//...
}
And I would like to use my methods selectParam and/or select to fill my datatable, but I don't know how to do that.
Although others complain at your learning attempt, everyone has to start somewhere. Your method is actually an ok start, but I would change the parameter from a string to a DbCommand object. Then, you can create your methods to properly build the command and set proper parameters. Then pass the entire prepared command to your wrapper method (that creates connection, tests open successful, queries data, etc) and have your method return a DataTable object as you have... something like
public class CL_MPG
{
private DataTable GetData(DbCommand cmd )
{
// do all the same as you have with exception of your USING DBCOMMAND.
// just set the connection property of the incoming command to that of
// your connection created
// AT THIS PART --
// using (DbCommand cmd = conn.CreateCommand())
// {
// cmd.CommandText = query;
// just change to below and remove the closing curly bracket for using dbcommand
cmd.Connection = conn;
}
// Now, your generic methods that you want to expose for querying
// something like
public DataTable GetAllData()
{
DbCommand cmd = new DbCommand( "select * from YourTable" );
return GetData( cmd );
}
public DataTable GetUser( int someIDParameter )
{
DbCommand cmd = new DbCommand( "select * from YourTable where ID = #parmID" );
cmd.Parameters.Add( "#parmID", someIDParameter );
return GetData( cmd );
}
public DataTable FindByLastName( string someIDParameter )
{
DbCommand cmd = new DbCommand( "select * from YourTable where LastName like #parmTest" );
cmd.Parameters.Add( "#parmTest", someIDParameter );
return GetData( cmd );
}
}
Notice the command is being built and fully prepared and parameterized vs concatination of strings as prior comment was made which could expose you to SQL-injection. As for the parameters, and not querying Oracle, they may need to be tweaked some. Different engines use slightly different conventions. If connecting to SQL-Server database, it uses "#" to identify a parameter. In SyBase Advantage Database, it uses ":". Using Visual FoxPro, a simple "?" placeholder is used.
Also, if your query has many criteria, just keep adding additional "#parm" type placeholders, then add your parameters in the same order as they appear in your query just to make sure you didn't miss any. Some functions could have none, one or more based on your needs. Then, in the samples provided, its as simple as doing something like
DataTable whoIs = yourCL_MPGObject.GetUser( 23 );
if( whoIs.Rows.Count > 0 )
MessageBox.Show( whoIs.Rows[0]["WhateverColumnName"] );

Pervasive SQL System Stored Procedure from ADO.NET error

I'm just trying to return a list of columns and their attributes through a system stored procedure. What documentation I have seems to say the below code should work, but I get "Pervasive.Data.SqlClient.Lna.k: [LNA][Pervasive][ODBC Engine Interface]Invalid or missing argument." on the execute. This is PSQL v11, .NET 4.5.
using (PsqlConnection conn = new PsqlConnection(cs))
{
PsqlCommand locationCmd = new PsqlCommand();
PsqlParameter tableParam = new PsqlParameter();
PsqlParameter returnParam = new PsqlParameter();
returnParam.Direction = ParameterDirection.ReturnValue;
locationCmd.CommandText = "psp_columns";
locationCmd.Connection = conn;
locationCmd.CommandType = CommandType.StoredProcedure;
locationCmd.Parameters.Add(tableParam).Value = table;
locationCmd.Parameters.Add(returnParam);
conn.Open();
locationCmd.ExecuteNonQuery();
}
I would think the problem is this line:
locationCmd.Parameters.Add(tableParam).Value = table;
You should set the value before adding the parameter, not afterwards.
tableParam.Value = table;
locationCmd.Parameters.Add(tableParam);
I don't know about Psql but for MSSQL normally you also need to define the parameter name as its found in the stored procedure, or at least that's what I do.
SqlParameter param = new SqlParameter("#tableParam", value);
The psp_Columns system stored procedure is defined as call psp_columns(['database_qualifier'],'table_name', ['column_name']). I know that it says the database qualifier is optional, but I think it's required. You could try passing an empty string for the qualifier. Something like:
using (PsqlConnection conn = new PsqlConnection(cs))
{
PsqlCommand locationCmd = new PsqlCommand();
PsqlParameter dbParam = new PsqlParameter();
PsqlParameter tableParam = new PsqlParameter();
PsqlParameter returnParam = new PsqlParameter();
returnParam.Direction = ParameterDirection.ReturnValue;
locationCmd.CommandText = "psp_columns";
locationCmd.Connection = conn;
locationCmd.CommandType = CommandType.StoredProcedure;
locationCmd.Parameters.Add(dbParam).Value = ""; //might need two single quotes ('')
locationCmd.Parameters.Add(tableParam).Value = table;
locationCmd.Parameters.Add(returnParam);
conn.Open();
locationCmd.ExecuteNonQuery();
}
You should try to get the information of the table SCHEMA using the provided GetSchema method from the Psqlconnection. I have searched a bit on their support site and it seems that this method is supported although I haven't find a direct example using the Tables collection.
This is just an example adapted from a test on mine on SqlServer, I don't have Pervasive install, but you could try if the results are the same
using(PsqlConnection cn = new PsqlConnection("your connection string here"))
{
cn.Open();
string[] selection = new string[] { null, null, table };
DataTable tbl = cn.GetSchema("Columns", selection);
foreach (DataRow row in tbl.Rows)
{
Console.WriteLine(row["COLUMN_NAME"].ToString() + " " +
row["IS_NULLABLE"].ToString() + " " +
row["DATA_TYPE"].ToString()
);
}
}
i was trying to figure this out as well, but with the tables procedure. even though the database and table names are optional, you still have to provide values. for optional parameters, pass in DBNull.Value
this worked for me:
PsqlCommand cm = new PsqlCommand();
cm.CommandText = "psp_tables";
cm.CommandType = CommandType.StoredProcedure;
cm.Connection = new PsqlConnection();
cm.Connection.ConnectionString = <your connection string>;
cm.Parameters.Add(":database_qualifier", DBNull.Value);
cm.Parameters.Add(":table_name", DBNull.Value);
cm.Parameters.Add(":table_type", "User table");

How to create sql connection with c# code behind, access the sql server then conditionally redirect?

This is a question from an experienced beginner!
Using ASP.NET 4 C# AND SQL server,
I have a connection string in web.config to myDatabase named "myCS".
I have a database named myDB.
I have a table named myTable with a primary key named myPK
What are the NECESSARY lines of code behind (minimal code) to create a SQL connection, then select from myTable where myPK=="simpleText"
it will probably include:
sqlconnection conn = new sqlconnection(??? myCS)
string SQLcommand = select * from myDB.myTable where myPK==myTestString;
sqlCommand command = new SqlCommand(SQL,conn);
conn.Open();
booleanFlag = ????
conn.Close();
conn.Dispose();
then
If ( theAnswer != NULL ) // or (if flag)
{
Response.Redirect("Page1.aspx");
}
else
{
Response.Redirect("Page2.aspx");
}
Here is a limited simple tutorial:
First, you want to have a class to do the hard work for you, then you will use it with ease.
First, you have to crate the connection string in your web.config file and name it.
Here it is named DatabaseConnectionString, but you may named it myCS as required in the question.
Now, in App_Code create a new class file and name it SqlComm (this is just an example name) like:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
public class SqlComm
{
// this is a shortcut for your connection string
static string DatabaseConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["dbConStr"].ConnectionString;
// this is for just executing sql command with no value to return
public static void SqlExecute(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
// with this you will be able to return a value
public static object SqlReturn(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
object result = (object)cmd.ExecuteScalar();
return result;
}
}
// with this you can retrieve an entire table or part of it
public static DataTable SqlDataTable(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
DataTable TempTable = new DataTable();
TempTable.Load(cmd.ExecuteReader());
return TempTable;
}
}
// sooner or later you will probably use stored procedures.
// you can use this in order to execute a stored procedure with 1 parameter
// it will work for returning a value or just executing with no returns
public static object SqlStoredProcedure1Param(string StoredProcedure, string PrmName1, object Param1)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter(PrmName1, Param1.ToString()));
cmd.Connection.Open();
object obj = new object();
obj = cmd.ExecuteScalar();
return obj;
}
}
}
Okay, this only a class, and now you should know how to use it:
If you wish to execute a command like delete, insert, update etc. use this:
SqlComm.SqlExecute("TRUNCATE TABLE Table1");
but if you need to retrieve a specific value from the database use this:
int myRequiredScalar = 0;
object obj = new object();
obj = SqlComm.SqlReturn("SELECT TOP 1 Col1 FROM Table1");
if (obj != null) myRequiredScalar = (int)obj;
You can retrieve a bunch of rows from the database this way (others like other ways)
This is relevant to your sepecific question
int Col1Value = 0;
DataTable dt = new DataTable();
dt = SqlComm.SqlDataTable("SELECT * FROM myTable WHERE myPK='simpleText'");
if (dt.Rows.Count == 0)
{
// do something if the query return no rows
// you may insert the relevant redirection you asked for
}
else
{
// Get the value of Col1 in the 3rd row (0 is the first row)
Col1Value = (int)dt.Rows[2]["Col1"];
// or just make the other redirection from your question
}
If you need to execute a stored procedure with or without returning a value back this is the way to do that (in this example there are no returning value)
SqlComm.SqlStoredProcedure1Param("TheStoredProcedureName", "TheParameterName", TheParameterValue);
Again, for your specific question return the table using the SqlDataTable , and redirect if dt.Rows.Count >0
Have fun.
There are many ways: LINQ, SqlDataReader, SQLDataAdapter, according to what you want to read (single value, datatable ...), so here is an example:
using (SqlConnection con = new SqlConnection("SomeConnectionString"))
{
var cmd = new SqlCommand("select from myTable where myPK==N'"+ simpleText+ "'",con);
cmd.Connection.Open();
var sqlReader = cmd.ExecuteReader();
while(sqlReader.Read())
{
//Fill some data like : string result = sqlReader("SomeFieldName");
}
sqlReader.Close();
cmd.Connection.Close();
cmd.Dispose();
}

Categories