Stored Procedure in Orchard - sql

Hi We are working on a project and i am trying to call a stored procedure. I have searched for the solution but i didn't find any way that how to call a stored procedure so can any one please tell me how to execute stored procedure.

How ever finally i am using the below code to execute the stored procedure and get the result.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress))
{
// temporary scope for new connection and setting stored procedure, parameters, and return RecordName list
using (SqlConnection cn = new SqlConnection(_settingsManager.LoadSettings().First().DataConnectionString))
{
if (cn.State == ConnectionState.Closed)
{
cn.Open();
}
const string storedProcedure = "usp_spName";
SqlCommand cmd = new SqlCommand(storedProcedure, cn);
cmd.Parameters.AddWithValue("#IsVerified", "value");
cmd.Parameters.AddWithValue("#page", "value");
// for out put parameter
cmd.Parameters.AddWithValue("#totalRows", 0);
cmd.Parameters["#totalRows"].Direction = ParameterDirection.Output;
cmd.CommandType = CommandType.StoredProcedure;
IDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
// To Get The Values of the result
int id=Convert.ToInt32(reader["Id"].ToString());
}
reader.Close();
try
{
// To Get the Out Put Perameter
totalRecords = (int)cmd.Parameters["#totalRows"].Value;
}
catch
{
totalRecords = 0;
}
cmd.Parameters.Clear();
cmd.Dispose();
cn.Close();
}
}

actually, I don't know about stored procedures, but you can call stored functions using code like examaple below. I'm new to C# and orchard, so may be my approach is not correct and good enough. At first you should get ISessionLocator object instance, using IOrchardServices, then create NHibernate ISession instance and then IQuery/ISQLQuery with CreateSQLQuery().
here is example code of Services class
public class ExampleService {
private readonly IOrchardServices _oServices;
public EParamsServices(IOrchardServices oServices) {
_oServices = oServices;
}
public float GetRegionPopulationDencity(int rId){
//resolve ISession locator (you can do this using dependencies in ctor)
ISessionLocator sl = _oServices.WorkContext.Resolve<ISessionLocator>();
//create session
ISession _session = sl.For(null);
// create raw SQL query
return _session.CreateSQLQuery(#"SELECT data.RegionDencity(:rId) as result")
.AddScalar("result", NHibernateUtil.Single)
.SetParameter<int>("rId", rId)
.List<float>()
.FirstOrDefault<float>();
}
}
I think you can exec stored procs the same way, just change SQL code do exec yourProcName and ExecuteUpdate() instead of List() method (I'm not sure in this part)
you also should add reference to NHibernate assembly to your project and add NHibernate & Orchard.Data to your using part.

You have to reference NHibernate and System.Data in your module , then you can use the below code
var cmd = _transactionManager.GetSession().Connection.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "MyStoredProcedure";
_transactionManager.GetSession().Transaction.Enlist(cmd);
cmd.ExecuteNonQuery();

Related

Could not GetActiveTransaction

I need to call stored procedure in my App Service. I'm following this tutorial to create a custom repository. But I could not find the Context.Database.
Here is the code:
[UnitOfWork]
public virtual async Task<List<string>> GetUserNames()
{
EnsureConnectionOpen();
using (var command = CreateCommand("GetUsernames", CommandType.storedProcedure))
{
using (var dataReader = await command.ExecuteReaderAsync())
{
var result = new List<string>();
while (dataReader.Read())
{
result.Add(dataReader["UserName"].ToString());
}
return result;
}
}
}
What is the Context.Database and how do I use it?
My application is MVC in .Net4.6.1.
Update 1
I have resolved this issue by inheriting MyApplicationRepositoryBase.
Now I face a new issue when trying to GetActiveTransaction. I don't have any idea about this. What can I do?
Here is the code:
private DbTransaction GetActiveTransaction()
{
return (DbTransaction)_transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
{
{"ContextType", typeof(MyDbContext) },
{"MultiTenancySide", MultiTenancySide }
});
}
Here is the error log:
System.NullReferenceException: Object reference not set to an instance of an object.
at Abp.EntityFramework.EfActiveTransactionProvider.GetActiveTransaction(ActiveTransactionProviderArgs args) in D:\Github\aspnetboilerplate\src\Abp.EntityFramework\EntityFramework\EfActiveTransactionProvider.cs:line 21
Update 2
I tried to comment out the command.Transaction and it worked:
private DbCommand CreateCommand(string commandText, CommandType commandType, params SqlParameter[] parameters)
{
var command = Context.Database.GetDbConnection().CreateCommand();
command.CommandText = commandText;
command.CommandType = commandType;
// command.Transaction = GetActiveTransaction();
foreach (var parameter in parameters)
{
command.Parameters.Add(parameter);
}
return command;
}
I still need to put my code under a Transaction, so I don't want to comment out this line. What should I do?
Now I faced the new issue when trying to get Active Transaction
Add this in PreInitialize method of YourProjectNameDataModule:
Configuration.ReplaceService<IEfTransactionStrategy, DbContextEfTransactionStrategy>(DependencyLifeStyle.Transien‌​t);

How to design Database Access Layer to contain Sql libraries in one place

I have a handler class for every table and I am doing all the DB work in functions, like below.
public class MyObjectHandler
{
public bool Insert(MyObject obj)
{
using(SqlConnection conn = new SqlConnection(DbHandler.ConnectionString))
{
SqlCommand comm = new SqlCommand("OBJ_INSERT", conn);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("#Code", SqlDbType.NVarChar, 50) { Value = obj.Code });
comm.Parameters.Add(new SqlParameter("#Desc", SqlDbType.NVarChar, 150) { Value = obj.Desc });
comm.Parameters.Add(new SqlParameter("#UserId", SqlDbType.Int) { Value = obj.UserCreated.Id });
conn.Open();
int retVal = comm.ExecuteNonQuery();
conn.Close();
if(retVal > 0)
return true;
else
return false;
}
}
public bool Update(MyObject obj)
{
using(SqlConnection conn = new SqlConnection(DbHandler.ConnectionString))
{
SqlCommand comm = new SqlCommand("OBJ_UPDATE", conn);
comm.Parameters.Add(new SqlParameter("#Id", SqlDbType.Int) { Value = obj.Id });
comm.Parameters.Add(new SqlParameter("#Code", SqlDbType.NVarChar, 50) { Value = obj.Code });
comm.Parameters.Add(new SqlParameter("#Desc", SqlDbType.NVarChar, 150) { Value = obj.Desc });
comm.CommandType = CommandType.StoredProcedure;
conn.Open();
int retVal = comm.ExecuteNonQuery();
conn.Close();
if(retVal > 0)
return true;
else
return false;
}
}
public bool Delete(int Id)
{
using(SqlConnection conn = new SqlConnection(DbHandler.ConnectionString))
{
SqlCommand comm = new SqlCommand("OBJ_DELETE", conn);
comm.Parameters.Add(new SqlParameter("#Id", SqlDbType.Int) { Value = Id });
comm.CommandType = CommandType.StoredProcedure;
conn.Open();
int retVal = comm.ExecuteNonQuery();
conn.Close();
if(retVal > 0)
return true;
else
return false;
}
}
}
Problem is, as you can see I am using SqlConnection routine all the time.
I want to create a layer, which is a class that includes all the SQL libraries.
Would you offer me a general solution on this? Even a general idea will be enough on this.
For example, my function for Getting the data is easy:
public static DataTable GetDataTable(string spName)
{
DataTable resultsTable = new DataTable();
using(SqlConnection conn = new SqlConnection(DbHandler.ConnectionString))
{
SqlCommand comm = new SqlCommand(spName, conn);
comm.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter(comm);
adapter.Fill(resultsTable);
conn.Close();
}
return resultsTable;
}
This is good enough, but I need a better solution to send parameters easily and with more flexibility. Seems like the only option is to send parameter name, type and length one by one. Would you recommend a design on this?
Consider using ORM with Repository pattern. ORMs are really great tools to build Data Access Layer. Dapper and NHibernate are my favorite; there are lot many other available.
Problem is, as you can see I am using "SqlConnection" routine all the time. I want to create a layer, which is a class includes all the Sql libraries. Would you offer me a general solution on this? Even a general idea will be enough on this.
General solution is ORM. General idea (without using ORM) could be to implement UnitOfWork pattern. Refer this answer. It is using Dapper ORM, but similar could be implemented with core ADO.NET. Repository pattern comes to rescue here. Instead of managing connection inside Repository, you can inject it from application. This way, your application gets total control over UnitOfWork and can use it the way suits for given situation.
I need a better solution to send parameters easier, and with more flexibility. Seems like the only option is to send parameter name, type and length one by one.
ORMs provide their own wrappers to accept the parameters; so it may help here. Without ORM, you can pass in Dictionay or similar and build parameter list inside your GetDataTable and pass it to ADO.NET call.

Can't Insert Data into DataBase(SQL) using MVC

This is my controller class
[HttpPost]
public ActionResult SignUp(SignupModel model)
{
User u = new User();
u.LoginId = model.LoginId;
u.Password = model.Password;
u.FullName = model.FullName;
new UsersHandler().AddUser(u);}
UserHandler class contains
public void AddUser(User user)
{
new DAC().Insert(user);
}
DAC class contains the connections and UsersDAC contains the queries
Insert Query
internal void Insert(User user)
{
List<SqlParameter> temp = new List<SqlParameter>
{
new SqlParameter("#FullName", user.FullName),
new SqlParameter("#LoginId", user.LoginId),
new SqlParameter("#Password", user.Password)
};
SqlConnection con = DACHelper.GetConnection();
using (con)
{
con.Open();
SqlTransaction t = con.BeginTransaction();
try
{
user.Id = (int)DACHelper.ExecuteScalar(INSERT, temp, t);
DACHelper.Execute(INSERT, temp);
t.Commit();
}
catch (Exception)
{
t.Rollback();
}
}
}
DACHelper.Execute(INSERT, temp);
It Executes but doesn't Insert any thing in table.
Stored Procedure
ALTER PROCEDURE [dbo].[Users_Insert]
#FullName varchar(50),
#LoginId varchar(50),
#Password varchar(50)
AS
Insert into [Users]
([FullName],[LoginId],[Password])
Values (#FullName,#LoginId,#Password)
Select ##IDENTITY from [Users]
My suggestions:
Test the stored procedure outside of your program using the same SQL credentials used by the program. If this works, the problem is your code.
Try calling the stored procedure by building the code without the use of your classes that hide some of what is being done.
Make sure that the SqlCommand object knows that it should be using a CommandType of CommandType.StoredProcedure.
Do not use SCOPE_IDENTITY or ##IDENTITY. The safest way to get the identity field is as follows (assume the field name is ID):
INSERT into [Users] ([FullName],[LoginID],[Password])
OUTPUT INSERTED.ID
VALUES (#FullName, #LoginID, #Password)
This will always be the correct value.
What about the commit mode? Is it in auto-commit mode. If not try to execute commit manually using the script. This should display message as transaction is committed.
You do not have used sqlparamater.appwithvalue may be this cause this issue..
internal void Insert(User user)
{
List<SqlParameter> temp = new List<SqlParameter>
{
new SqlParameter().AddWithvalue("#FullName", user.FullName),
new SqlParameter().AddWithvalue("#LoginId", user.LoginId),
new SqlParameter().AddWithvalue("#Password", user.Password)
};
SqlConnection con = DACHelper.GetConnection();
using (con)
{
con.Open();
SqlTransaction t = con.BeginTransaction();
try
{
user.Id = (int)DACHelper.ExecuteScalar(INSERT, temp, t);
DACHelper.Execute(INSERT, temp);
t.Commit();
}
catch (Exception)
{
t.Rollback();
}
}
}
internal void Insert(User user)
{
List<SqlParameter> temp = new List<SqlParameter>
{
new SqlParameter("#LoginId", user.LoginId),
new SqlParameter("#Password", user.Password),
new SqlParameter("#FullName", user.FullName),
};
SqlConnection con = DACHelper.GetConnection();
using (con)
{
con.Open();
SqlTransaction t = con.BeginTransaction();
user.Id = (Int32)DACHelper.ExecuteScalar(INSERT, temp, t);
t.Commit();
}
}
This will work by removing try/catch.

ExecuteNonQueryAsync hangs in MVC app

I have a DAL project I call from my MVC controller. I pass the method a list of objects I want updated. I added break points and it gets to ExecuteNonQueryAsync() and then just hangs. The website keeps "loading" and it never gets to return 1; The query worked before I tried to move it to execute async (you can see where I commented out the execution of the query. I did delete the connection open/close pieces but the query worked fine before this.
Also I updated the code below so I can post it with OBJECT, ListObjects and COL1/COL2 instead of the actual values/object names used.
Thanks in advance!
static async Task<int> NonQuery(System.Data.SqlClient.SqlConnection conn, System.Data.SqlClient.SqlCommand cmd)
{
await conn.OpenAsync();
await cmd.ExecuteNonQueryAsync();
return 1;
}
public static bool updateQuery(List<OBJECT> listObjects)
{
string cnn = System.Configuration.ConfigurationManager.ConnectionStrings["connstring"].ToString();
using (System.Data.SqlClient.SqlConnection mySqlConnection = new System.Data.SqlClient.SqlConnection(cnn))
{
StringBuilder SQLQuery = new StringBuilder();
SQLQuery.AppendLine("UPDATE TABLENAME ");
SQLQuery.AppendLine("SET COL1 = #COL1, ");
SQLQuery.AppendLine("WHERE COL2 = #COL2 ");
//mySqlConnection.Open();
foreach (ObjectType ot in listObjects)
{
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(SQLQuery.ToString(), mySqlConnection);
cmd.Parameters.Add("#COL1", System.Data.SqlDbType.Int).Value = COL1VALUE;
cmd.Parameters.Add("#COL2", System.Data.SqlDbType.Int).Value = COL2VALUE;
int result = NonQuery(mySqlConnection, cmd).Result;
//cmd.ExecuteNonQuery();
}
//mySqlConnection.Close();
}
As I describe on my blog, this is a common problem when converting your code to async. The proper solution is to replace all Result and Wait calls with await, as such:
public static async Task<bool> updateQueryAsync(List<OBJECT> listObjects)
{
...
int result = await NonQueryAsync(mySqlConnection, cmd);
...
}
static async Task<int> NonQueryAsync(SqlConnection conn, SqlCommand cmd)
I also changed your async methods to end in Async, as specified by the TAP documentation.

How to convert SQL to LINQ?

Here is my IsValid user login code in MVC4 model.
I'm trying to have my SQL command convert to LINQ.
How can I convert it to LINQ way?
public bool IsValid(string _username, string _password)
{
using (var cn = new SqlConnection(#"Data Source=(LocalDB)\v11.0;AttachDbFilename" +
#"='C:\Tutorials\1 - Creating a custom user login form\Creating " +
#"a custom user login form\App_Data\Database1.mdf';Integrated Security=True"))
{
string _sql = #"SELECT [Username] FROM [dbo].[System_Users] " +
#"WHERE [Username] = #u AND [Password] = #p";
var cmd = new SqlCommand(_sql, cn);
cmd.Parameters
.Add(new SqlParameter("#u", SqlDbType.NVarChar))
.Value = _username;
cmd.Parameters
.Add(new SqlParameter("#p", SqlDbType.NVarChar))
.Value = Helpers.SHA1.Encode(_password);
cn.Open();
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Dispose();
cmd.Dispose();
return true;
}
else
{
reader.Dispose();
cmd.Dispose();
return false;
}
}
}
After you've LINQ or any ORM setup for your application, it can be converted to simple LINQ statement.
return _dbContext.Users.Any(c=>c.UserName == _username && c.Password == Helpers.SHA1.Encode(_password));
I would first look at using an Entity Data Model like the ones in Entity Framework (http://msdn.microsoft.com/en-gb/data/ef.aspx) to model your database objects in C# and add one to your project.
Then I would create a Stored Procedure in your DB to handle the execution of the SQL statement, passing in the parameters you want to test against.
Then, I would import the stored procedure into the Data Model and run a LINQ query against it.
Something along the lines of:
var valid = (from users in context.CheckUserMembership(userName: userName, password: password)
select new User
{
UserId = users.UserId,
UserName = users.Username
}).Count() > 0;
Where context is a reference to the Data Context generated by the Entity Data Model wizard and CheckUserMembership is the imported stored procedure containing your SQL statement.