I am using EF Core 1.0 in an ASP.NET Core App. Can you please point me to the proper way of executing stored procedures? The old method with ObjectParameters
and ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction
is not working.

- 16,398
- 7
- 76
- 175

- 23,151
- 18
- 48
- 71
-
1You need to run the SP and get some `DbSet` in result? Or just run it? – haim770 Feb 19 '15 at 09:09
-
I need to get the results back! – eadam Feb 19 '15 at 12:29
-
For simplest and most complete answer, check this out: https://stackoverflow.com/a/75465142/8644294 – Ash K Feb 15 '23 at 20:30
20 Answers
Support for stored procedures in EF Core 1.0 is resolved now, this also supports the mapping of multiple result-sets.
Check here for the fix details
And you can call it like this in c#
var userType = dbContext.Set().FromSql("dbo.SomeSproc @Id = {0}, @Name = {1}", 45, "Ada");

- 16,398
- 7
- 76
- 175

- 1,232
- 9
- 8
-
2find another great example here - http://www.dotnetjalps.com/2015/11/stored-procedure-entity-framework-codefirst.html This is self explanatory. – Arvin Dec 16 '15 at 12:38
-
Mark this as an answer to help other user recognize that the support is now available. – Arvin Dec 31 '15 at 06:32
-
1Multiple datasets are NOT yet supported. See https://github.com/aspnet/EntityFramework/issues/1864#issuecomment-170709883 – AperioOculus Apr 01 '16 at 14:39
-
5my 2 cents: var UserId =1; _dbCtx.Set
().FromSql($"dbo.StoredProcedureName @UserId= {UserId}"); //just syntax sugar... – hidden Jun 12 '16 at 07:48 -
-
like any POCO that respresents exactly the fields that the stored procedure is returning. For example if the stored proc returns a column called FirstName then you create a POCO with a property called FIrstName and it will automatically map it to it. You also need to decorate one of your properties with [Key] attribute... but i consider that a bug but EF forces you to because you need to add the stored procedure to your DbSet – hidden Jul 03 '16 at 21:29
-
12See this if you like me cant find fromSql: http://dotnetthoughts.net/how-to-execute-storedprocedure-in-ef-core/ "To get the FromSql command, you need to add the reference of “Microsoft.EntityFrameworkCore.Relational” package in your project.json file." Also add using Microsoft.EntityFrameworkCore; – Ernesto Jan 10 '17 at 17:28
-
1Sadly you can't seem to use `Set()` in EF Core 1.1. Just get `The arguments for DbContext.Set
() cannot be inferred from the usage` – Douglas Gaskell Feb 27 '17 at 05:54 -
Is there any way to get output parameters. I am trying var y = await _customerContext.Customers.FromSql("usp_CustomerAll_sel @SomeOutput out", parameters: votesParam).ToArrayAsync();..no luck – Rahul Chowdhury Apr 25 '17 at 18:44
-
This returns IQueryable
so you can append ToList() for getting the result set or ToListAsync() for async call. – MSK Jul 04 '18 at 13:28
To execute the stored procedures, use FromSql method which executes RAW SQL queries
e.g.
var products= context.Products
.FromSql("EXECUTE dbo.GetProducts")
.ToList();
To use with parameters
var productCategory= "Electronics";
var product = context.Products
.FromSql("EXECUTE dbo.GetProductByCategory {0}", productCategory)
.ToList();
or
var productCategory= new SqlParameter("productCategory", "Electronics");
var product = context.Product
.FromSql("EXECUTE dbo.GetProductByName @productCategory", productCategory)
.ToList();
There are certain limitations to execute RAW SQL queries or stored procedures. You can’t use it for INSERT/UPDATE/DELETE. if you want to execute INSERT, UPDATE, DELETE queries, use the ExecuteSqlCommand
var categoryName = "Electronics";
dataContext.Database
.ExecuteSqlCommand("dbo.InsertCategory @p0", categoryName);

- 1,093
- 1
- 15
- 22

- 5,527
- 3
- 27
- 31
-
7The method `ExecuteSqlCommand` is now obsolete. See [ExecuteSqlCommand Method](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.relationaldatabasefacadeextensions.executesqlcommand?view=efcore-3.1) Possible alternatives are `ExecuteSqlRaw` and `ExecuteSqlInterpolated`. – Pablo Alexis Domínguez Grau Apr 25 '20 at 08:56
Stored procedure support is not yet (as of 7.0.0-beta3) implemented in EF7. You can track the progress of this feature using issue #245.
For now, you can do it the old fashioned way using ADO.NET.
var connection = (SqlConnection)context.Database.AsSqlServer().Connection.DbConnection;
var command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "MySproc";
command.Parameters.AddWithValue("@MyParameter", 42);
command.ExecuteNonQuery();

- 28,825
- 9
- 92
- 117
-
-
2That's [#624](https://github.com/aspnet/EntityFramework/issues/624). ;) You can always do it on the ADO.NET connection: `context.Database.AsRelational().Connection.DbConnection`. – bricelam Feb 19 '15 at 22:38
-
Down voting. See @Arvin's answer as this is now supported in EF Core. – Jim Wooley Apr 13 '16 at 13:18
-
3@JimWooley That seems a little unethical... But yes, use `FromSql` now. – bricelam Apr 18 '16 at 04:24
-
7@JimWooley LOL, not sure if you're aware of it or not, but you downvoted an answer of one of the main developers in the EF team... :) – gdoron May 15 '16 at 09:41
-
I think this answer should be updated to reflect the change or refer to the other answer since, from my perspective and I think what @JimWooley was getting at, this is no longer the best answer. – Richard Marskell - Drackir Sep 14 '16 at 18:58
-
4@RichardMarskell-Drackir StackOverflow answers are very much a point-in-time thing. Do you really expect everyone to keep all their answers up-to-date for the rest of time? Either the asker should pick a different answer or the community should upvote better ones that come along. Bad form on the downvote. – bricelam Sep 15 '16 at 15:40
-
1@bricelam - I disagree that answers should be considered point-in-time. I occasionally go back to old high-vote answers to see if anything has changed so new searches are still relevant, but I realize that not everyone does this. Many times I've come to SO from a search and started using the accepted answer only to later see that there was a better answer further down. I agree it would be good if the asker updated the answer but it's likely that they get what they came for and move on. Anyhow, I think it would be helpful for people coming from Google to know there's a better way to do this. :) – Richard Marskell - Drackir Sep 15 '16 at 16:51
-
you could use https://github.com/verdie-g/StoredProcedureEFCore, which is mentioned in the thread to issue #245. – Manfred Wippel Apr 25 '19 at 11:45
-
I get the error "DatabaseFacade does not contain a definition for "AsSqlServer" and no accessible extension method "AsSqlServer" accepting a first argument "DatabaseFacade " could be found – Markus Aug 30 '19 at 15:33
-
But I added using System.Data.SqlClient; then I could use var connection = (SqlConnection)context.Database.GetDbConnection(); – Markus Aug 30 '19 at 15:44
The support for stored procedure in EF Core is similar to the earlier versions of EF Code first.
You need to create your DbContext class by inherting the DbContext class from EF. The stored procedures are executing using the DbContext.
First step is to write a method that create a DbCommand from the DbContext.
public static DbCommand LoadStoredProc(
this DbContext context, string storedProcName)
{
var cmd = context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = storedProcName;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
return cmd;
}
To pass parameters to the stored procedure use the following method.
public static DbCommand WithSqlParam(
this DbCommand cmd, string paramName, object paramValue)
{
if (string.IsNullOrEmpty(cmd.CommandText))
throw new InvalidOperationException(
"Call LoadStoredProc before using this method");
var param = cmd.CreateParameter();
param.ParameterName = paramName;
param.Value = paramValue;
cmd.Parameters.Add(param);
return cmd;
}
Finally for mapping the result into a list of custom objects use the MapToList method.
private static List<T> MapToList<T>(this DbDataReader dr)
{
var objList = new List<T>();
var props = typeof(T).GetRuntimeProperties();
var colMapping = dr.GetColumnSchema()
.Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
.ToDictionary(key => key.ColumnName.ToLower());
if (dr.HasRows)
{
while (dr.Read())
{
T obj = Activator.CreateInstance<T>();
foreach (var prop in props)
{
var val =
dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
prop.SetValue(obj, val == DBNull.Value ? null : val);
}
objList.Add(obj);
}
}
return objList;
}
Now we’re ready for execute the stored procedute with the ExecuteStoredProc method and maps it to the a List whose type that’s passed in as T.
public static async Task<List<T>> ExecuteStoredProc<T>(this DbCommand command)
{
using (command)
{
if (command.Connection.State == System.Data.ConnectionState.Closed)
command.Connection.Open();
try
{
using (var reader = await command.ExecuteReaderAsync())
{
return reader.MapToList<T>();
}
}
catch(Exception e)
{
throw (e);
}
finally
{
command.Connection.Close();
}
}
}
For example, to execute a stored procedure called “StoredProcedureName” with two parameters called “firstparamname” and “secondparamname” this is the implementation.
List<MyType> myTypeList = new List<MyType>();
using(var context = new MyDbContext())
{
myTypeList = context.LoadStoredProc("StoredProcedureName")
.WithSqlParam("firstparamname", firstParamValue)
.WithSqlParam("secondparamname", secondParamValue).
.ExecureStoredProc<MyType>();
}

- 3,563
- 3
- 27
- 32

- 1,460
- 1
- 12
- 22
I tried all the other solutions but didn't worked for me. But I came to a proper solution and it may be helpful for someone here.
To call a stored procedure and get the result into a list of model in EF Core, we have to follow 3 steps.
Step 1.
You need to add a new class just like your entity class. Which should have properties with all the columns in your SP. For example if your SP is returning two columns called Id
and Name
then your new class should be something like
public class MySPModel
{
public int Id {get; set;}
public string Name {get; set;}
}
Step 2.
Then you have to add one DbQuery
property into your DBContext class for your SP.
public partial class Sonar_Health_AppointmentsContext : DbContext
{
public virtual DbSet<Booking> Booking { get; set; } // your existing DbSets
...
public virtual DbQuery<MySPModel> MySP { get; set; } // your new DbQuery
...
}
Step 3.
Now you will be able to call and get the result from your SP from your DBContext.
var result = await _context.Query<MySPModel>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
I am using a generic UnitOfWork & Repository. So my function to execute the SP is
/// <summary>
/// Execute function. Be extra care when using this function as there is a risk for SQL injection
/// </summary>
public async Task<IEnumerable<T>> ExecuteFuntion<T>(string functionName, string parameter) where T : class
{
return await _context.Query<T>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
}
Hope it will be helpful for someone !!!

- 4,128
- 1
- 24
- 24
-
I was hoping to avoid doing this. I'd written my own libraries (pre EF) to handle dynamic dataset (e.g. joins and the like) then the worked flawlessly. Everyone just whinged so I moved to EF which you can't do that now. Guess what, they asked me to rewrite my libraries. My response wasn't pleasant. – djack109 May 11 '20 at 12:28
"(SqlConnection)context"
-- This type-casting no longer works. You can do: "SqlConnection context;
".AsSqlServer()"
-- Does not Exist.
"command.ExecuteNonQuery();"
-- Does not return results. reader=command.ExecuteReader()
does work.
With dt.load(reader)... then you have to switch the framework out of 5.0 and back to 4.51, as 5.0 does not support datatables/datasets, yet. Note: This is VS2015 RC.

- 14,434
- 2
- 26
- 40

- 59
- 1
- 1
I had a lot of trouble with the ExecuteSqlCommand
and ExecuteSqlCommandAsync
, IN parameters were easy, but OUT parameters were very difficult.
I had to revert to using DbCommand
like so -
DbCommand cmd = _context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = "dbo.sp_DoSomething";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar) { Value = "Steve" });
cmd.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar) { Value = "Smith" });
cmd.Parameters.Add(new SqlParameter("@id", SqlDbType.BigInt) { Direction = ParameterDirection.Output });
I wrote more about it in this post.

- 5,065
- 10
- 51
- 68
Currently EF 7 or EF Core does not support the old method of importing Stored procedures in designer and calling them directly. You can have a look at the roadmap to see what is going to be supported in the future: EF core roadmap.
So for now it is better to use SqlConnection to call stored procedures or any raw query, since you do not need the entire EF for this job. Here are two examples:
Call stored procedure that return single value. String in this case.
CREATE PROCEDURE [dbo].[Test]
@UserName nvarchar(50)
AS
BEGIN
SELECT 'Name is: '+@UserName;
END
Call stored procedure that return a list.
CREATE PROCEDURE [dbo].[TestList]
AS
BEGIN
SELECT [UserName], [Id] FROM [dbo].[AspNetUsers]
END
To call these stored procedure it is better to create static class that holds all of these functions, for example, I called it DataAccess class, as follows:
public static class DataAccess
{
private static string connectionString = ""; //Your connection string
public static string Test(String userName)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
// 1. create a command object identifying the stored procedure
SqlCommand cmd = new SqlCommand("dbo.Test", conn);
// 2. set the command object so it knows to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which will be passed to the stored procedure
cmd.Parameters.Add(new SqlParameter("@UserName", userName));
// execute the command
using (var rdr = cmd.ExecuteReader())
{
if (rdr.Read())
{
return rdr[0].ToString();
}
else
{
return null;
}
}
}
}
public static IList<Users> TestList()
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
// 1. create a command object identifying the stored procedure
SqlCommand cmd = new SqlCommand("dbo.TestList", conn);
// 2. set the command object so it knows to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// execute the command
using (var rdr = cmd.ExecuteReader())
{
IList<Users> result = new List<Users>();
//3. Loop through rows
while (rdr.Read())
{
//Get each column
result.Add(new Users() { UserName = (string)rdr.GetString(0), Id = rdr.GetString(1) });
}
return result;
}
}
}
}
And Users class is like this:
public class Users
{
public string UserName { set; get; }
public string Id { set; get; }
}
By the way you do not need to worry about the performance of opening and closing a connection for every request to sql as the asp.net is taking care of managing these for you. And I hope this was helpful.

- 305
- 4
- 13
Since it is agreed in my team that we are going to use generic UnitOfWork pattern, I have taken a bit of everyone's solutions when creating mine.
I am posting a bit of UnitOfWork code as well so you can get a grasp of why I needed to implement it like so.
public interface IUnitOfWork : IDisposable
{
DbContext Context { get; }
Task<List<T>> ExecuteStoredProc<T>(string storedProcName, Dictionary<string, object> procParams) where T : class;
}
Interface implementation:
public class UnitOfWork : IUnitOfWork
{
public DbContext Context { get; private set; }
/// <summary>
/// Execute procedure from database using it's name and params that is protected from the SQL injection attacks.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="storedProcName">Name of the procedure that should be executed.</param>
/// <param name="procParams">Dictionary of params that procedure takes. </param>
/// <returns>List of objects that are mapped in T type, returned by procedure.</returns>
public async Task<List<T>> ExecuteStoredProc<T>(string storedProcName, Dictionary<string, object> procParams) where T : class
{
DbConnection conn = Context.Database.GetDbConnection();
try
{
if(conn.State != ConnectionState.Open)
await conn.OpenAsync();
await using (DbCommand command = conn.CreateCommand())
{
command.CommandText = storedProcName;
command.CommandType = CommandType.StoredProcedure;
foreach (KeyValuePair<string, object> procParam in procParams)
{
DbParameter param = command.CreateParameter();
param.ParameterName = procParam.Key;
param.Value = procParam.Value;
command.Parameters.Add(param);
}
DbDataReader reader = await command.ExecuteReaderAsync();
List<T> objList = new List<T>();
IEnumerable<PropertyInfo> props = typeof(T).GetRuntimeProperties();
Dictionary<string, DbColumn> colMapping = reader.GetColumnSchema()
.Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
.ToDictionary(key => key.ColumnName.ToLower());
if (reader.HasRows)
{
while (await reader.ReadAsync())
{
T obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in props)
{
object val =
reader.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
prop.SetValue(obj, val == DBNull.Value ? null : val);
}
objList.Add(obj);
}
}
reader.Dispose();
return objList;
}
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message, e.InnerException);
}
finally
{
conn.Close();
}
return null; // default state
}
Example usage is like so:
public class MyService : IMyService
{
private readonly IUnitOfWork _uow;
public MyService(IUnitOfWork uow)
{
_uow = uow;
}
public async Task<List<TreeViewModel>> GetTreeOptions()
{
var procParams = new Dictionary<string, object>()
{
{"@Id", 2}
};
var result = await _uow.ExecuteStoredProc<TreeViewModel>("FetchTreeProcedure", procParams);
return result;
}
}

- 615
- 3
- 13
- 31
I found this extention very usefull: StoredProcedureEFCore
Then the usage is like this
List<Model> rows = null;
ctx.LoadStoredProc("dbo.ListAll")
.AddParam("limit", 300L)
.AddParam("limitOut", out IOutParam<long> limitOut)
.Exec(r => rows = r.ToList<Model>());
long limitOutValue = limitOut.Value;
ctx.LoadStoredProc("dbo.ReturnBoolean")
.AddParam("boolean_to_return", true)
.ReturnValue(out IOutParam<bool> retParam)
.ExecNonQuery();
bool b = retParam.Value;
ctx.LoadStoredProc("dbo.ListAll")
.AddParam("limit", 1L)
.ExecScalar(out long l);

- 1,946
- 1
- 15
- 14
It's embarrassing how lacking the docs are on this.
It took me a lot of hit and trial to figure this out , so I wanted to document it here so someone else doesn't have to spend time figuring this out. I'm using Entity Framework Core Version 6.0.10
.
Summary
There are 2 kinds of Stored Procedures that return result. And the approach to call them and get result is different from each other.
SPs that return table-based output.
SPs that return output in the output parameters.
SPs that return table based output
If your SP looks like this:
CREATE PROCEDURE dbo.MyTestSPToGetShopType @ShopId AS VARCHAR(25)
AS
SELECT ShopId, ShopType
FROM Shop
WHERE SHOPID = @ShopId
Step 1: Create a class based on your output
public class MyTestSpResult
{
public string ShopId { get; set; }
public string ShopType { get; set; }
}
Step 2:
Register this in your DbContext's protected override void OnModelCreating(ModelBuilder builder)
method:
builder.Entity<MyTestSpResult>(e => e.HasNoKey());
Step 3: Call the SP from the code, and get the result:
var myTestSpResult = await _dbContext.Set<MyTestSpResult>()
.FromSqlInterpolated($"EXEC dbo.MyTestSPToGetShopType @ShopId = \"A03\"")
.ToArrayAsync();
var myShopType = myTestSpResult[0].ShopType;
Alternate Way
Steps 1 and 2 are same as above.
Step 3: Register the class from Step 1 in your DbContext:
public virtual DbSet<MyTestSpResult> MyTestSpResult { get; set; }
Step 4: Call the SP from the code, and get the result:
var mySPResult = await _dbContext.MyTestSpResult
.FromSqlInterpolated($"EXEC dbo.MyTestSPToGetShopType @ShopId = \"A03\"")
.ToArrayAsync();
var myShopType = mySPResult[0].ShopType;
SPs that return output in the output parameters
If your SP looks like this:
CREATE PROCEDURE dbo.MyOtherTestSPToGetShopType
(
@ShopId VARCHAR(25)
,@ShopType VARCHAR(25) OUTPUT
)
AS
SELECT @ShopType = ShopType
FROM Shop
WHERE SHOPID = @ShopId
Step 1: Create the SQL parameters:
var shopId = new SqlParameter()
{
ParameterName = "@ShopId",
Value = "A03",
Direction = System.Data.ParameterDirection.Input,
SqlDbType = System.Data.SqlDbType.VarChar,
Size = 25
};
var shopType = new SqlParameter()
{
ParameterName = "@ShopType",
Direction = System.Data.ParameterDirection.Output,
SqlDbType = System.Data.SqlDbType.VarChar,
Size = 25
};
Step 2: Call the SP from code using those parameters, and get the result:
await _dbContext.Database
.ExecuteSqlInterpolatedAsync($"EXEC dbo.MyOtherTestSPToGetShopType @ShopId = {shopId}, @ShopType = {shopType} OUT");
var myShopType = shopType.Value as string;

- 1,802
- 17
- 44
-
What about SPs that return multiple result sets? EF 6 seems to support that scenario. Didn't find anything on EF Core – tasin95 Feb 21 '23 at 10:42
-
@tasin95 I haven't done this myself, but I think you can use the first approach in this answer to do that as well. Inside your `MyTestSpResult` model, create List properties to model your set. Then just call the SP; `myTestSpResult[0]` will have the first set, `myTestSpResult[1]` will have the second set and so on. – Ash K Feb 22 '23 at 15:36
Using MySQL connector and Entity Framework Core 2.0
My issue was that I was getting an exception like fx. Ex.Message = "The required column 'body' was not present in the results of a 'FromSql' operation.". So, in order to fetch rows via a stored procedure in this manner, you must return all columns for that entity type which the DBSet is associated with, even if you don't need to access all of it for your current request.
var result = _context.DBSetName.FromSql($"call storedProcedureName()").ToList();
OR with parameters
var result = _context.DBSetName.FromSql($"call storedProcedureName({optionalParam1})").ToList();

- 1,196
- 14
- 16
I'm using Entity Framework Core with my ASP.Net Core 3.x WebAPI. I wanted one of my end points just to execute a particular Stored Procedure, and this is the code I needed:
namespace MikesBank.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ResetController : ControllerBase
{
private readonly MikesBankContext _context;
public ResetController(MikesBankContext context)
{
_context = context;
}
[HttpGet]
public async Task<ActionResult> Get()
{
try
{
using (DbConnection conn = _context.Database.GetDbConnection())
{
if (conn.State != System.Data.ConnectionState.Open)
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = "Reset_Data";
await cmd.ExecuteNonQueryAsync();
}
return new OkObjectResult(1);
}
catch (Exception ex)
{
return new BadRequestObjectResult(ex.Message);
}
}
}
}
Notice how I need to get my DbContext
which has been injected, but I also need to Open()
this connection.

- 27,846
- 7
- 149
- 159
Create the special class according the fields in your Select query of your stored procedure. For example I will call this class ResulData
Add to context of you EF
modelBuilder.Entity<ResultData>(e =>
{
e.HasNoKey();
});
And this a sample function to get data using the store procedure
public async Task<IEnumerable<ResultData>> GetDetailsData(int id, string name)
{
var pId = new SqlParameter("@Id", id);
var pName = new SqlParameter("@Name", name);
return await _context.Set<ResultData>()
.FromSqlRaw("Execute sp_GetDeailsData @Id @Name", parameters: new[] { pId, pName })
.ToArrayAsync();
}

- 40,935
- 4
- 18
- 45
-
-
@AshK you have to create this class and add it to your dbcontext. You can not create an anonymous class – Serge Feb 14 '23 at 21:13
I used StoredProcedureEFCore nuget package by https://github.com/verdie-g/StoredProcedureEFCore,EnterpriseLibrary.Data.NetCore,EFCor.SqlServer,EFCore.Tools
I tried DbFirst approach with {Repository pattern}.. i think so
startup.cs
ConfigureServices(IServiceCollection services){
services.AddDbContext<AppDbContext>(opt => opt
.UseSqlServer(Configuration.GetConnectionString("SampleConnectionString")));
services.AddScoped<ISomeDAL, SomeDAL>();
}
public class AppDbContext : DbContext{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{}
}
ISomeDAl Interface has {GetPropertiesResponse GetAllPropertiesByCity(int CityId);}
public class SomeDAL : ISomeDAL
{
private readonly AppDbContext context;
public SomeDAL(AppDbContext context)
{
this.context = context;
}
public GetPropertiesResponse GetAllPropertiesByCity(int CityId)
{
//Create Required Objects for response
//wont support ref Objects through params
context.LoadStoredProc(SQL_STATEMENT)
.AddParam("CityID", CityId).Exec( r =>
{
while (r.Read())
{
ORMapping<GenericRespStatus> orm = new ORMapping<GenericRespStatus>();
orm.AssignObject(r, _Status);
}
if (r.NextResult())
{
while (r.Read())
{
Property = new Property();
ORMapping<Property> orm = new ORMapping<Property>();
orm.AssignObject(r, Property);
_propertyDetailsResult.Add(Property);
}
}
});
return new GetPropertiesResponse{Status=_Status,PropertyDetails=_propertyDetailsResult};
}
}
public class GetPropertiesResponse
{
public GenericRespStatus Status;
public List<Property> PropertyDetails;
public GetPropertiesResponse()
{
PropertyDetails = new List<Property>();
}
}
public class GenericRespStatus
{
public int ResCode { get; set; }
public string ResMsg { get; set; }
}
internal class ORMapping<T>
{
public void AssignObject(IDataReader record, T myClass)
{
PropertyInfo[] propertyInfos = typeof(T).GetProperties();
for (int i = 0; i < record.FieldCount; i++)
{
if (propertyInfos.Any(obj => obj.Name == record.GetName(i))) //&& record.GetValue(i) != DBNull.Value
{
propertyInfos.Single(obj => obj.Name == record.GetName(i)).SetValue(myClass, Convert.ChangeType(record.GetValue(i), record.GetFieldType(i)));
}
}
}
}

- 3,752
- 35
- 31
- 35

- 29
- 3
From EF core 3.0
onwards, we can also use the following commands:
dbContext.Database.ExecuteSqlInterpolated()
:
var name = "Ramin";
var outArticleCount = new SqlParameter(
"@outArticleCount",
SqlDbType.Int) { Direction = ParameterDirection.Output };
dbContext.Database.ExecuteSqlInterpolated(
$"exec dbo.MySp {name}, {outputArticleCount} out");
dbContext.Database.ExecuteSqlInterpolatedAsync()
:dbContext.Database.ExecuteSqlRaw()
:
SqlParameter[] parameters =
{
new SqlParameter("@name", SqlDbType.Varchar { Direction = ParameterDirection.Input, Value = "Ramin" },
new SqlParameter("@outArticleCount", SqlDbType.Int { Direction = ParameterDirection.Output }
}
dbContext.Database.ExecuteSqlRaw("exec dbo.MySp @name, @outArticleCount OUTPUT", parameters);
dbContext.Database.ExecuteSqlRawAsync()
Raw
and Interpolated
versions of above methods are equal but Interpolated versions are safe against SQL Injection
attacks (read more here and here).

- 16,499
- 9
- 69
- 98
If you are executing a stored procedure from Informix using EntityFrameworkCore you need to include the command EXECUTE PROCEDURE
var spresult = _informixContext.procdata.FromSql("EXECUTE PROCEDURE dummyproc ({0},{1},{2})", parameters: new[] { p0, p1,p2 }).ToList();
Nothing have to do... when you are creating dbcontext for code first approach initialize namespace below the fluent API area make list of sp and use it another place where you want.
public partial class JobScheduleSmsEntities : DbContext
{
public JobScheduleSmsEntities()
: base("name=JobScheduleSmsEntities")
{
Database.SetInitializer<JobScheduleSmsEntities>(new CreateDatabaseIfNotExists<JobScheduleSmsEntities>());
}
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<ReachargeDetail> ReachargeDetails { get; set; }
public virtual DbSet<RoleMaster> RoleMasters { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.Types().Configure(t => t.MapToStoredProcedures());
//modelBuilder.Entity<RoleMaster>()
// .HasMany(e => e.Customers)
// .WithRequired(e => e.RoleMaster)
// .HasForeignKey(e => e.RoleID)
// .WillCascadeOnDelete(false);
}
public virtual List<Sp_CustomerDetails02> Sp_CustomerDetails()
{
//return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Sp_CustomerDetails02>("Sp_CustomerDetails");
// this.Database.SqlQuery<Sp_CustomerDetails02>("Sp_CustomerDetails");
using (JobScheduleSmsEntities db = new JobScheduleSmsEntities())
{
return db.Database.SqlQuery<Sp_CustomerDetails02>("Sp_CustomerDetails").ToList();
}
}
}
}
public partial class Sp_CustomerDetails02
{
public long? ID { get; set; }
public string Name { get; set; }
public string CustomerID { get; set; }
public long? CustID { get; set; }
public long? Customer_ID { get; set; }
public decimal? Amount { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int? CountDay { get; set; }
public int? EndDateCountDay { get; set; }
public DateTime? RenewDate { get; set; }
public bool? IsSMS { get; set; }
public bool? IsActive { get; set; }
public string Contact { get; set; }
}

- 873
- 7
- 12
I'm using Entity Framework Core. The support for stored procedures and adhoc queries doesn't feel as fluid as it does in Framework.
Here are some examples for future reference:
Populate a list of entities from the results of a stored procedure:
The [dbo].[GetUnarchivedJobs]
stored procedure returns a list of records that matches the Job
entity.
We can use the FromSqlInterpolated()
method on the Jobs
property to call the stored procedure and have a list of Job
returned.
NoTracking()
is used to speed up the performance, and in this case we wont be updating the entities.
using Microsoft.EntityFrameworkCore;
public class DbContext : Microsoft.EntityFrameworkCore.DbContext
{
protected DbSet<Job> Jobs { get; set; }
// Populate a list of entities from the results of a stored procedure
public Task<List<Job>> GetUnarchivedJobs(int maxQty, CancellationToken cancellationToken) =>
Jobs.FromSqlInterpolated($"EXEC [dbo].[GetUnarchivedJobs] @MaxQty = {maxQty}")
.AsNoTracking()
.ToListAsync(cancellationToken)
;
public DbContext(DbContextOptions<DbContext> options) : base(options) { }
}
Send an array of integers to a stored procedure:
The [dbo].[SetJobListArchiveFlags]
stored procedure has a single parameter of type integer_list_tbltype
.
We need to create a DataTable
to match the integer_list_tbltype
type which has a single column named n
.
The int
values need to be added to the DataTable
.
A SqlParameter
is used to pass the populated DataTable
to the stored procedure.
Because we are not populating any entities, we need to use methods on the Database
property to call the stored procedure.
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System.Data;
public class DbContext : Microsoft.EntityFrameworkCore.DbContext
{
// Send an array of integers to a stored procedure
public async Task<int> MarkJobsAsArchived(IEnumerable<int> jobIds, CancellationToken cancellationToken)
{
// This DataTable matches the `integer_list_tbltype` db type
var table = new DataTable();
table.Columns.Add("n", typeof(int));
foreach (var id in jobIds) table.Rows.Add(id);
var parameter = new SqlParameter("@jobIds", SqlDbType.Structured);
parameter.Value = table;
parameter.TypeName = "integer_list_tbltype";
var rowsUpdatedCount = await Database.ExecuteSqlRawAsync("EXEC [dbo].[SetJobListArchiveFlags] @jobIds", new[] { parameter }, cancellationToken);
return rowsUpdatedCount;
}
}

- 9,017
- 3
- 42
- 63
We should create a property with DbQuery not DbSet in the model for the db context like below...
public class MyContextContext : DbContext
{
public virtual DbQuery<CheckoutInvoiceModel> CheckoutInvoice { get; set; }
}
After than a method that can be used to return result
public async Task<IEnumerable<CheckoutInvoiceModel>> GetLabReceiptByReceiptNo(string labReceiptNo)
{
var listing = new List<CheckoutInvoiceModel>();
try
{
var sqlCommand = $@"[dbo].[Checkout_GetLabReceiptByReceiptNo] {labReceiptNo}";
listing = await db.Set<CheckoutInvoiceModel>().FromSqlRaw(sqlCommand).ToListAsync();
}
catch (Exception ex)
{
return null;
}
return listing;
}
From above example, we can use any one option you like.
Hope this helpful for you!

- 1,339
- 1
- 17
- 19
-
You never use this property `CheckoutInvoice`. And it's not clear where `LoadStoredProc` comes from. – Gert Arnold Nov 01 '20 at 20:09
-
Yes, this is possible to add CheckoutInvoice in DbContext, But it should be DbQuery, not DbSet. Well, LoadStoredProc is comming from
Note: I'm using Core version: 3.18 Thanks @GertArnold – Rejwanul Reja Nov 02 '20 at 16:10