I have never used asynchronous calls, could some one please provide me a sample how to call a SQL stored procedure from MVC controller ?
public ActionResult ReProcess(string uname)
{
SqlCommand cmd=new SqlCommand();
cmd.Connection = cnn;
cnn.Open();
cmd.CommandText = "dbo.userdetails_sp";
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
cmd.Parameters.Add("#userId", System.Data.SqlDbType.VarChar).Value = uname; ;
cmd.ExecuteNonQuery();
}
You can use the Task class to encapsulate a method and then run it asyncronously:
http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx
var t = Task.Factory.StartNew(() => DoAction());
Related
I have ASP.NET Core 2.2 application using EF Core. In startup.cs i am setting CommandTimeout to 60 seconds
services.AddDbContext<CrowdReason.WMP.Data.Entities.WMPContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
sqlServerOptions => sqlServerOptions.CommandTimeout(60)));
Then i am executing the stored proc using the following code. Please note the values of t1, t2 and t3 in comments
public static async Task<int?> prcDoWork(this WMPContext dbContext, int id, int userID)
{
var t1 = dbContext.Database.GetCommandTimeout();
// t1 is 60. Same as what i set in startup.cs
using (var connection = dbContext.Database.GetDbConnection())
{
var t2 = connection.ConnectionTimeout;
//t2 is 15
using (var cmd = connection.CreateCommand())
{
var p1 = new SqlParameter("#ID", SqlDbType.Int)
{
Value = id
};
var p2 = new SqlParameter("#UserID", SqlDbType.Int)
{
Value = userID
};
cmd.CommandText = "dbo.prcDoWork";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
var t3 = cmd.CommandTimeout;
//t3 is 30
await dbContext.Database.OpenConnectionAsync().ConfigureAwait(false);
var result = await cmd.ExecuteScalarAsync().ConfigureAwait(false);
if (result != null)
{
return Convert.ToInt32(result);
}
return null;
}
}
}
I understand that ConnectionTimeout is different from CommandTimeout.
However issue is when i create command using connection.CreateCommand() its not automatically getting the timeout from DBContext
EF Core works on top of the underlying System.Data implementation (in your case System.Data.SqlClient) and uses it to perform its DB operations. All settings you make will only reflect the way EF uses this underlying implementation.
When you use the GetDbConnection method you get a reference to an SqlConnection class from the System.Data.SqlClient assembly that knows nothing about EF and its settings and cannot be expected to honor the RelationalOptionsExtension.CommandTimeout from the Microsoft.EntityFrameworkCore.Relational assembly.
To have EF settings respected you should use the RelationalDatabaseFacadeExtensions.ExecuteSqlCommandAsync method.
Below is my code and I get an error at ExecuteNonQuery:
#Name parameter missing.
I have tried many time and even no error during building of program. The stored procedure contains an insert statement with 4 parameters, 3 of varchar type and one integer type as the primary key.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace CompanyMaster
{
public class Master
{
public IEnumerable<Company> Companies
{
get
{
string connectionString = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
List<Company> companies = new List<Company>();
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("spGetAllCompany", con);
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Company company = new Company();
company.CompanyCode = Convert.ToInt32(rdr["CompanyCode"]);
company.CompanyName = rdr["CompanyName"].ToString();
company.CompanyAddress = rdr["CompanyAddress"].ToString();
company.CompanyMail = rdr["CompanyMail"].ToString();
companies.Add(company);
}
}
return companies;
}
}
public void Addcompany(Company company)
{
string connectionString = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("spAddCompany", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
SqlParameter paramCode = new SqlParameter();
paramCode.ParameterName = "#Code";
paramCode.Value = company.CompanyCode;
cmd.Parameters.Add(paramCode);
SqlParameter PName = new SqlParameter("#Name", SqlDbType.VarChar, 50);
//PName.ParameterName = "#Name";
PName.Value = company.CompanyName;
cmd.Parameters.Add(PName);
SqlParameter paramAddress = new SqlParameter();
paramAddress.ParameterName = "#Address";
paramAddress.Value = company.CompanyAddress;
cmd.Parameters.Add(paramAddress);
SqlParameter paramMail = new SqlParameter();
paramMail.ParameterName = "#Mail";
paramMail.Value = company.CompanyMail;
cmd.Parameters.Add(paramMail);
con.Open();
cmd.ExecuteNonQuery();-- error is occurring here
}
}
}
}
Here is my stored procedure:
CREATE PROCEDURE spAddCompany
#Code INT,
#Name NVARCHAR(50),
#Address NVARCHAR(60),
#Mail NVARCHAR(50)
AS
BEGIN
INSERT INTO CompanyMaster (CompanyCode, CompanyName, CompanyAddress, CompanyMail)
VALUES (#Code, #Name, #Address, #Mail)
END
#Name parameter is missing when the code reaches ExecuteNonQuery.
I think your problem has to do with null vs DBNull.Value.
Check if company.CompanyName is null (in c#). If it is, you should pass DBNull.Value instead.
For more information on the difference between the two, read What is the difference between null and System.DBNull.Value?
From Configuring Parameters and Parameter Data Types:
Note
When you send a null parameter value to the server, you must specify DBNull, not null (Nothing in Visual Basic). The null value in the system is an empty object that has no value. DBNull is used to represent null values. For more information about database nulls, see Handling Null Values.
Also, You can add parameters to the command and set their values in a single line of code, like this:
cmd.Parameters.Add("#Name", SqlDbType.NVarChar, 50).Value = company.CompanyName;
This will make your code much shorter and more readable.
Here are the changes I've made to your code that I think should solve your problem:
public void Addcompany(Company company)
{
string connectionString = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (var con = new SqlConnection(connectionString))
{
// SqlCommand also implements the IDisposable interface
using(var cmd = new SqlCommand("spAddCompany", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Code", SqlDbType.Int).Value = company.CompanyCode;
cmd.Parameters.Add("#Name", SqlDbType.VarChar, 50).Value = company.CompanyName as object ?? (object)DBNull.Value;
cmd.Parameters.Add("#Address", SqlDbType.VarChar, 50).Value = company.CompanyAddress as object ?? (object)DBNull.Value;
cmd.Parameters.Add("#Mail", SqlDbType.VarChar, 50).Value = company.CompanyMail as object ?? (object)DBNull.Value;
con.Open();
cmd.ExecuteNonQuery();
}
}
}
Note the use of the null coalescing operator (??) and the casting to object.
I'm using a stored procedure to update a table when the user clicks approve however I get message that it was approved successfully but the table wasn't updated.
Update
I'm now only able to update one item; even I select more than one item it is only updating one.
Stored Procedure
Update RequisitionItem
set [status] = 0,
[approve_date] = #approve_date
--[ApprovedBy]=#ApprovedBy
where [status]=-1 and Req_No=#reqNumber and item_no=#item_no
Method
public void SetRequisitionStatus0(List <string> reqNumber,List <string> item_no)
{
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand();
command.CommandText = "requisition_sp_setstatus0";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#reqNumber", SqlDbType.VarChar);
command.Parameters.Add("#item_no", SqlDbType.VarChar);
//command.Parameters.Add("#ApprovedBy", SqlDbType.VarChar);
command.Parameters.Add("#approve_date", SqlDbType.DateTime).Value = DateTime.Now;
using (command.Connection = connection)
{
try
{
connection.Open();
foreach (var item in reqNumbers)
{
command.Parameters["#reqNumber"].Value = item;
foreach (var item1 in item_no)
{
command.Parameters["#item_no"].Value = item1;
}
command.ExecuteNonQuery();
}
}
finally
{
connection.Close();
}
}
return;
}
I think the foreach loops are messing you up. The inner loop will loop the entire list (item_no) then go back to the outer loop, then the inner loop will go through the entire list again, always giving you the last item. You need a for loop, something like
for(int i = 0; i < reqNumbers.count; i++)
{
command.Parameters["#reqNumber"].Value = reqNumbers[i];
command.Parameters["#item_no"].Value = item_no[i];
command.ExecuteNonQuery();
}
you don't need to close the connection either - the using statement will close it automatically. and you don't need the final return.
I have the following statements:
SqlConnection con = new SqlConnection(ConfigurationManager.AppSettings["DataBaseName"]);
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "update Table1 set data = #data where id = #id";
cmd.Parameters.AddWithValue("#data", SqlDbType.VarChar).Value = data;
cmd.Parameters.AddWithValue("#id", SqlDbType.Int).Value = id;
cmd.CommandType = CommandType.Text;
try
{
DataSet ds = new DataSet();
con.Open();
cmd.Prepare();
cmd.ExecuteNonQuery();
return true;
}
When executing cmd.Prepare() I have an error SqlCommand.Prepare method requires all parameters to have an explicitly set type
I read some answers here, but looks like I did as described here
but still have the same problem.
What am I missing?
Somebody please help me by modying this code.when i retrieve the Login value through stored procedure call, i am getting this error message "Procedure or function 'GetUserLogin' expects parameter '#UserName', which was not supplied."
Here is my code:
public int GetLogin(string UserName, string Password)
{
SqlConnection con = new SqlConnection(str);
SqlDataAdapter da = new SqlDataAdapter("GetUserLogin", con);
SqlCommand com = new SqlCommand("GetUserLogin",con);
com.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
da.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
if ((ds.Tables[0].Rows[0].ItemArray[1].ToString() == UserName) && (ds.Tables[0].Rows[0].ItemArray[2].ToString() == Password))
{
return 1;
}
else
{
return 0;
}
}
else
{
return -1;
}
StoredProcedure:
CREATE PROCEDURE GetUserLogin #UserName varchar(50)
AS
select UserName,
Password
From Login where UserName=#UserName
RETURN
Thanks,
Masum
You need to add a UserName parameter to your command. Do something like this after you create your command, but before you execute it:
com.Parameters.Add("#UserName", SqlDbType.VarChar, 50);
com.Parameters["#UserName"].Value = UserName;
Add this before you fill the dataset
cmd.Parameters.AddWithValue("UserName",UserName);