Passing SqlParameter in webmethod asp.net - asp.net

I am trying to create a web service which will help to execute stored procedure. And that web method I am calling in my code to execute a stored procedure. This is my web method -
[WebMethod(Description = des_ExecuteParamerizedSelectCommand)]
public DataTable ExecuteParamerizedSelectCommand(string CommandName, CommandType cmdType, SqlParameter[] param)
{
DataTable table = new DataTable();
using (SqlConnection con = new SqlConnection(ConnectionString()))
{
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = cmdType;
cmd.CommandText = CommandName;
cmd.Parameters.AddRange(param);
try
{
if (con.State != ConnectionState.Open)
{
con.Open();
}
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(table);
}
}
catch
{
throw;
}
}
}
return table;
}
Now this is my code in my data access layer - when I am trying to call this web method, its throwing compile time error.
Error 2 Argument 2: cannot convert from 'System.Data.CommandType' to 'DAL.sqlDBHelper.CommandType'
Error 3 Argument 3: cannot convert from 'System.Data.SqlClient.SqlParameter[]' to 'DAL.sqlDBHelper.SqlParameter[]'
My code to call the webmethod -
sqlDBHelper.ODCdbHelper mysqlDBHelper = new sqlDBHelper.ODCdbHelper();
public Login GetUserRoles(string _Idsid)
{
Login login = null;
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#UserName", _Idsid)
};
//Lets get the list of all employees in a datataable
using (DataTable table = mysqlDBHelper.ExecuteParamerizedSelectCommand("GetUserRole", CommandType.StoredProcedure, parameters))
Can you please tell me someone, where I am wrong??
Thanks in advance
Gulrej

Try like this
DAL.sqlDBHelper.SqlParameter[] parameters = new DAL.sqlDBHelper.SqlParameter[]//Change Here {
SqlParameter("#UserName", _Idsid)
};
//Lets get the list of all employees in a datataable
using (DataTable table = mysqlDBHelper.ExecuteParamerizedSelectCommand("GetUserRole", DAL.sqlDBHelper.CommandType.StoredProcedure, parameters))

I presume DAL.sqlDBHelper.CommandType will be an enumerator in your data access layer.
And the expected parameter is DAL.sqlDBHelper.SqlParameter[] instead of System.Data.SqlClient.SqlParameter[]
So you might call the select function as
DAL.sqlDBHelper.SqlParameter[] parameters = new DAL.sqlDBHelper.SqlParameter[]
{
new SqlParameter("#UserName", _Idsid)
};
using (DataTable table = mysqlDBHelper.ExecuteParamerizedSelectCommand("GetUserRole", DAL.sqlDBHelper.CommandType.StoredProcedure, parameters))
Please check what is the command type defined for stored procedures in your DAL.

Related

Chnage format return of DotNet

I created web API using dotNet. It work but i got a little problem.
This is my controller
WaybillDataAccessLayer objway = new WaybillDataAccessLayer();
public IEnumerable<Waybill> Get(string id_wb)
{
List<Waybill> lstWaybill = new List<Waybill>();
lstWaybill = objway.GetWaybill(id_wb).ToList();
return lstWaybill;
}
and my Models(WaybillDataAccessLayer)
public IEnumerable<Waybill> GetWaybill(String id_wb)
{
List<Waybill> lswaybill = new List<Waybill>();
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("spGetWaybill", con); //Stored procedure on database
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#waybill", id_wb);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read()) //foreach
{
Waybill wb = new Waybill();
wb.waybill = rdr["waybill"].ToString();
wb.deskripsi = rdr["deskripsi"].ToString();
wb.tanggal = rdr["tanggal"].ToString();
wb.pengirim = rdr["pengirim"].ToString();
wb.lokasi = rdr["lokasi"].ToString();
wb.penerima = rdr["penerima"].ToString();
lswaybill.Add(wb);
}
con.Close();
}
return lswaybill;
}
when i run this API,the output will be like this
[
{
"waybill": "00000093",
"deskripsi": "SPARE PARTS",
"tanggal": "19990727",
"pengirim": "JIEP",
"lokasi": "HO",
"penerima": "JKHO"
}
]
My Question is
how to remove that [] ?
how to add another information like
{
"status" : "sucess",
"data" { }
}
Thankyou for your help.
You're returning a list of WayBill objects. If you don't want the resulting JSON to be an array, then you need to just return a single WayBill, not a List. And if you want to wrap that in more data, then create a type to represent that information, populate an instance of it, and return it.
Since you're retrieving these objects by ID, I'm assuming there should be only one WayBill for any given ID. Thus you can simplify your data access layer.
public Waybill GetWaybill(String id_wb)
{
using (SqlConnection con = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand("spGetWaybill", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#waybill", id_wb);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Read();
Waybill wb = new Waybill();
wb.waybill = rdr["waybill"].ToString();
wb.deskripsi = rdr["deskripsi"].ToString();
wb.tanggal = rdr["tanggal"].ToString();
wb.pengirim = rdr["pengirim"].ToString();
wb.lokasi = rdr["lokasi"].ToString();
wb.penerima = rdr["penerima"].ToString();
return wb;
}
}
And add the type to wrap your response:
class GetWayBillResponse()
{
public string Status { get; set;}
public WayBill WayBill { get; set; }
}
Note that adding a status here isn't really all that helpful if you're seeing the object, you can assume it was successful. Also, the API would have responded with an HTTP 200 OK status code. So it's really superfluous.
Now your controller becomes:
WaybillDataAccessLayer objway = new WaybillDataAccessLayer();
public GetWayBillResponse Get(string id_wb)
{
GetWayBillResponse response = new GetWayBillResponse();
response.Status = "Success";
response.WayBill = objway.GetWaybill(id_wb);
return response;
}
Note that you can simplify your data access even further. You're manually assigning the result columns to the WayBill object. That's repetitive and boring. If you use an Object Relational Mapper such as Dapper, you can remove a lot of that boiler plate code.
Here's what it'd look like using Dapper:
public Waybill GetWaybill(String id_wb)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
return con.QuerySingle<WayBill>("spGetWaybill", new { waybill = id_web }, commandType: CommandType.StoredProcedure);
}
}

How to use SqlConnection InfoMessage

I have this method that calls a stored procedure. My problem is that it does not return a row, but it prints a message. I am trying to capture that print message into a variable. My problem is I have never ever used InfoMessage before and I checked it out online and for the life of me I can't seem to understand it. Can someone help me out or point me in the right direction?
Here is my code:
public List<showWhatClass> showWhatMethod(string deviceWhat, int tagWhat, Decimal latit, Decimal longit, int Process, string CallNext, int CallNextVar)
{
showWhatCell = new List<showWhatClass>();
try
{
using (connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand("iosShowWhat", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#DeviceId", deviceWhat);
command.Parameters.AddWithValue("#TagId", tagWhat);
command.Parameters.AddWithValue("#Latitude", latit);
command.Parameters.AddWithValue("#Longitude", longit);
command.Parameters.AddWithValue("#Process", Process);
command.Parameters.AddWithValue("#CallNext", CallNext);
command.Parameters.AddWithValue("#CallNextVar", CallNextVar);
connection.Open();
/*SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
showWhatClass item = new showWhatClass();
item.CallNext = reader.GetValue(0).ToString();
item.CallNextVar = (int)reader.GetValue(1);
showWhatCell.Add(item);
}*/
}
}
}
finally
{
connection.Close();
}
return showWhatCell;
}
I have tried the following:
connection.Open();
connection.InfoMessage += delegate(object sender, SqlInfoMessageEventArgs e)
{
showWhatClass item = new showWhatClass();
item.CallNext += "\n" + e.Message;
showWhatCell.Add(item);
};
returns nothing.
You can use an output parameter to get the message from stored procedure and use it in your code.
Add output parameter in stored procedure
#name varchar(20) output
And then set value of this parameter
set #name='Mairaj Ahmad Minhas'
Now in your code when you call stored procedure add another parameter like this
command.Parameters.Add("#name", SqlDbType.VarChar, 20);
command.Parameters["#name"].Direction = ParameterDirection.Output;
And after you have called the stored procedure do this to get value from this parameter.
string name = command.Parameters["#name"].Value.ToString();

Populate web form edit page C# ASP.NET

I am trying to select a single row on a gridview and have that selection take me to a separate edit page with the data populated. I have the idea of using a session variable to hold the row id and then retrieving the data on page load and populating the text boxes. My question is whether or not this is the best method to go about doing this? I would prefer to not use the inline edit option in gridview as I have too many columns that would require scrolling horizontally. Here is my page load method using the session variable:
if (Session["editID"] != null)
{
dbCRUD db = new dbCRUD();
Recipe editRecipe = new Recipe();
var id = Convert.ToInt32(Session["editID"]);
Session.Remove("editID");
editRecipe = db.SelectRecord(id);
addName.Text = editRecipe.Name;
}
Here is the SelectRecord method that is used to retrieve the row:
public Recipe SelectRecord(int id)
{
Recipe returnedResult = new Recipe();
var dbConn = new SqlConnection(connString);
var dbCommand = new SqlCommand("dbo.selectRecipe", dbConn);
dbCommand.CommandType = CommandType.StoredProcedure;
dbCommand.Parameters.Add("#ID", SqlDbType.Int).Value = id;
dbConn.Open();
SqlDataReader reader = dbCommand.ExecuteReader();
while (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
dbConn.Close();
return returnedResult;
}
I'm probably not utilizing the SQLDataReader appropriately, but my result is no data in the reader therefore no returned data when calling the method. Any help is appreciated - thanks in advance!
Few things you should be aware of here:
1.
You should use while (reader.HasRows) in case your stored procedure returns multiple resultsets. In that case you have to iterate through the result sets. See Retrieving Data Using a DataReader. So, if selectRecipe returns multiple resultsets (I am assuming this is not the case), change your code to this:
while (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
reader.NextResult();
}
2.If selectRecipe returns single result set, change the while loop to if(){}:
if(reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
3. I would probably use using to manage the connection better (using Statement) :
public Recipe SelectRecord(int id)
{
Recipe returnedResult = new Recipe();
using (SqlConnection dbConn = new SqlConnection(connString))
{
var dbCommand = new SqlCommand("dbo.selectRecipe", dbConn);
dbCommand.CommandType = CommandType.StoredProcedure;
dbCommand.Parameters.AddWithValue("#ID", id);
dbConn.Open();
SqlDataReader reader = dbCommand.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
reader.Close();
}
return returnedResult;
}

SqDataReader closed issue in .net

i have created a function which executes query and returns SqlDataReader, now i am using that in another function work with the returned data, but i gets the error saying reader is already closed. here is the functions:
public static SqlDataReader ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
{
SqlDataReader reader = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(procedure, connection))
{
connection.Open();
if(parameters != null)
{
if (commandType == CommandType.StoredProcedure)
command.Parameters.AddRange(parameters);
}
reader = command.ExecuteReader();
}
}
return reader;
}
here is the code where i am calling the SqlDataReader
using (SqlDataReader reader = SqlHelper.ExecuteReader("select top 10 username from users", null, System.Data.CommandType.Text))
{
Response.Write(reader.IsClosed); //This returns True
}
EDIT
ExecuteReader with CommanBehavior ( automatically close connection after reading data)
To over come connection closing proble just make use of CommandBheviour
- CommandBehavior.CloseConnection
When you pass above values as argument to ExecuteReader
1. there is no need to close connection explicitly connection get close when you close your reader.
code will be like this no need to close connection explicitly
public void CreateMySqlDataReader(string mySelectQuery,string myConnectionString)
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
SqlCommand myCommand = new SqlCommand(mySelectQuery, myConnection);
myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
while(myReader.Read())
{
Console.WriteLine(myReader.GetString(0));
}
myReader.Close();
//Implicitly closes the connection because CommandBehavior.CloseConnection was specified.
}
its causing problem because you are closing connection
SqlReader always make use of open connection i.e live connection which is open when you use this
using (SqlConnection connection = new SqlConnection(connectionString))
{
}
it dispose connection object which is used by reader object that why its returing IsColosed as true
If you wanto return value the objec than make use of DataTable which is disconnected data object and doens makse use of connection
Modified code
public static DataTable ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
{
DataTable dt = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(procedure, connection))
{
connection.Open();
if(parameters != null)
{
if (commandType == CommandType.StoredProcedure)
command.Parameters.AddRange(parameters);
}
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(dt);
}
}
return dt;
}
DataReader needs an Open Connection. What you can do it either return a DataTable or Have custom class to represent the results of your SQL query and return an instance of that.
Create a Class to represent your Entity
public class Customer
{
public int ID { set;get;}
public string Name { set;get;}
}
And inside your method;
public List<Customer> GetCustomer()
{
List<Customer> custList=new List<Customer>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand("yourParameterizedSQLQuery",
connection))
{
//Add parameters if needed
connection.Open();
using (var reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
cust=new Customer();
while(reader.Read())
{
var cust=new Customer();
// TO DO :Do db null checking before reading
cust.ID=reader.GetInt32(reader.GetOrdinal("ID"));
cust.Name=reader.GetString(reader.GetOrdinal("Name"));
custList.Add(cust);
}
}
}
}
}
return custList;
}
The problem is that you have using SqlConnection which closes the connection to your database when leaving the scope.
SqlDataReader needs a "still open" connection. Returning it to the parent does not keep the connection open.
Your choice are basically to return a DataSet, which is an "unconnected" data source or change the way you manage your connection to open it, use the SqlDataReader, close the connection.
You may have to leave the connection open and let the calling code close the connection associated with the reader.
I had this challenge so I change my return type to DataTable
reader = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
return dt;
That way I don't have to worry about closing the connection outside that method

Reusable code to retrieve data

i have found an very good method for retrieving any result set from the database just by specifying the stored procedure name.i think the code is very much reusable.code is as follows
using System.Data;
using System.Data.SqlClient;
private DataSet GetFreshData(string sprocName)
{
using ( SqlConnection conn = new SqlConnection() )
{
using ( SqlDataAdapter da = new SqlDataAdapter() )
{
da.SelectCommand = new SqlCommand();
da.SelectCommand.CommandText = sprocName;
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Connection = conn;
DataSet ds = new DataSet();
try
{
da.SelectCommand.Connection.Open();
da.Fill(ds);
da.SelectCommand.Connection.Close();
}
catch
{
return null;
}
finally
{
// do other things...calling Close() or Dispose()
// for SqlConnection or SqlDataAdapter objects not necessary
// as its taken care of in the nested "using" statements
}
return ds;
}
}
}
my question is can someone suggest a modification to this method when the stored procedure need to specify several parameters
Easy! :) take a SqlParameter[] as the second argument to the function.
Then make sure da.SelectCommand.Parameters is filled with the list of SqlParameter objects in the SqlParameter[]

Resources