问题
I am using asp.net core application with abp(Asp.net BoilerPlate) framework. I want to use stored procedure to get the data and also to implement CRUD operations in this code first architecture. What will be best way to do so?
Thanks in advance
回答1:
Here is an example that sends a parameter to a stored procedure to delete a user:
public async Task DeleteUser(EntityDto input) { await Context.Database.ExecuteSqlCommandAsync( "EXEC DeleteUserById @id", default(CancellationToken), new SqlParameter("id", input.Id) ); }
See: Using Stored Procedure, User Defined Function and Views in a Custom Repository with ASP.NET Boilerplate
Source code is published on Github: https://github.com/aspnetboilerplate/aspnetboilerplate-samples/tree/master/StoredProcedureDemo
回答2:
Create your custom repository, so you can access the dbcontext object and execute sql query by using this context. I have created some helper methods in my custom repository, hope it can help you:
/// <summary>
/// Map data from datareader to list object
/// </summary>
private List<T> MapToList<T>(DbDataReader reader)
{
var result = new List<T>();
if (reader.HasRows)
{
var props = typeof(T).GetRuntimeProperties();
var colMapping = reader.GetColumnSchema().Where(x => props.Any(p => p.Name.Equals(x.ColumnName, StringComparison.OrdinalIgnoreCase))).ToDictionary(key => key.ColumnName.ToLower());
while (reader.Read())
{
var item = Activator.CreateInstance<T>();
foreach (var prop in props)
{
var propValue = reader.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
prop.SetValue(item, propValue == DBNull.Value ? null : propValue);
}
result.Add(item);
}
}
return result;
}
/// <summary>
/// Execute command return empty result
/// </summary>
public int ExecuteSqlCommand(string sqlCommand, Dictionary<string, object> @params)
{
List<SqlParameter> sqlParams = new List<SqlParameter>();
foreach (var item in @params)
{
if (item.Value != null)
sqlParams.Add(new SqlParameter(item.Key, item.Value));
else
sqlParams.Add(new SqlParameter(item.Key, DBNull.Value));
}
if (@params.Count > 0)
sqlCommand += " ";
sqlCommand += String.Join(",", @params.Select(p => p.Key));
return Context.Database.ExecuteSqlCommand(sqlCommand, sqlParams.ToArray());
}
/// <summary>
/// Execute stored procedure return set of rows
/// </summary>
public IEnumerable<TResult> ExecuteStoredProcedureWithRowsResult<TResult>(string name, Dictionary<string, object> @params) where TResult : class
{
//Fix exception: ExecuteReader requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.
UnitOfWorkManager.Current.Options.IsTransactional = false;
using (var command = Context.Database.GetDbConnection().CreateCommand())
{
var result = new List<TResult>();
string sqlCmd = String.Format("{0} ", name);
if (command.Connection.State != System.Data.ConnectionState.Open)
command.Connection.Open();
try
{
foreach (var item in @params)
{
if (item.Value != null)
command.Parameters.Add(new SqlParameter(item.Key, item.Value));
else
command.Parameters.Add(new SqlParameter(item.Key, DBNull.Value));
command.CommandText = sqlCmd;
command.CommandType = System.Data.CommandType.StoredProcedure;
using (var reader = command.ExecuteReader())
{
result = MapToList<TResult>(reader);
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
command.Connection.Close();
}
return result;
}
}
And in application service, inject your custom repository, and can call stored procedure like:
var @params = new Dictionary<string, object>();
@params.Add("Id", 1);
var result = _customRepository.ExecuteStoredProcedureWithRowsResult<UserResult>("sp_getUsers", @params);
回答3:
If you dont want to use EF, you can use Dapper, it is easy to use: http://www.c-sharpcorner.com/article/asp-net-core-web-api-with-dapper-and-vs-2017/
来源:https://stackoverflow.com/questions/46337728/how-to-use-stored-procedure-in-asp-net-core-with-boilerplate-architecture