How to call Stored Procedures with EntityFramework?

131,086

Solution 1

One way is to use the Database property off the DbContext:

SqlParameter param1 = new SqlParameter("@firstName", "Frank");
SqlParameter  param2 = new SqlParameter("@lastName", "Borland");
context.Database.ExecuteSqlCommand("sp_MyStoredProc @firstName, @lastName", 
                              param1, param2);

EF5 definitely supports that.

Solution 2

You have use the SqlQuery function and indicate the entity to mapping the result.

I send an example as to perform this:

var oficio= new SqlParameter
{
    ParameterName = "pOficio",
    Value = "0001"
};

using (var dc = new PCMContext())
{
    return dc.Database
             .SqlQuery<ProyectoReporte>("exec SP_GET_REPORTE @pOficio",
                                        oficio)
             .ToList();
}

Solution 3

Once your stored procedure is imported in your model, you can right click in it (from the model browser, in the Context.Store/Stored Procedures section), and click Add Function Import. If you need a complex type as a result, you can create it right there.

Solution 4

Based up the OP's original request to be able to called a stored proc like this...

using (Entities context = new Entities())
{
    context.MyStoreadProcedure(Parameters); 
}

Mindless passenger has a project that allows you to call a stored proc from entity frame work like this....

using (testentities te = new testentities())
{
    //-------------------------------------------------------------
    // Simple stored proc
    //-------------------------------------------------------------
    var parms1 = new testone() { inparm = "abcd" };
    var results1 = te.CallStoredProc<testone>(te.testoneproc, parms1);
    var r1 = results1.ToList<TestOneResultSet>();
}

... and I am working on a stored procedure framework (here) which you can call like in one of my test methods shown below...

[TestClass]
public class TenantDataBasedTests : BaseIntegrationTest
{
    [TestMethod]
    public void GetTenantForName_ReturnsOneRecord()
    {
        // ARRANGE
        const int expectedCount = 1;
        const string expectedName = "Me";

        // Build the paraemeters object
        var parameters = new GetTenantForTenantNameParameters
        {
            TenantName = expectedName
        };

        // get an instance of the stored procedure passing the parameters
        var procedure = new GetTenantForTenantNameProcedure(parameters);

        // Initialise the procedure name and schema from procedure attributes
        procedure.InitializeFromAttributes();

        // Add some tenants to context so we have something for the procedure to return!
        AddTenentsToContext(Context);

        // ACT
        // Get the results by calling the stored procedure from the context extention method 
        var results = Context.ExecuteStoredProcedure(procedure);

        // ASSERT
        Assert.AreEqual(expectedCount, results.Count);
    }
}

internal class GetTenantForTenantNameParameters
{
    [Name("TenantName")]
    [Size(100)]
    [ParameterDbType(SqlDbType.VarChar)]
    public string TenantName { get; set; }
}

[Schema("app")]
[Name("Tenant_GetForTenantName")]
internal class GetTenantForTenantNameProcedure
    : StoredProcedureBase<TenantResultRow, GetTenantForTenantNameParameters>
{
    public GetTenantForTenantNameProcedure(
        GetTenantForTenantNameParameters parameters)
        : base(parameters)
    {
    }
}

If either of those two approaches are any good?

Solution 5

Basically you just have to map the procedure to the entity using Stored Procedure Mapping.

Once mapped, you use the regular method for adding an item in EF, and it will use your stored procedure instead.

Please see: This Link for a walkthrough. The result will be adding an entity like so (which will actually use your stored procedure)

using (var ctx = new SchoolDBEntities())
        {
            Student stud = new Student();
            stud.StudentName = "New sp student";
            stud.StandardId = 262;

            ctx.Students.Add(stud);
            ctx.SaveChanges();
        }
Share:
131,086
Ivy
Author by

Ivy

Updated on May 12, 2020

Comments

  • Ivy
    Ivy almost 4 years

    I have generated an EF4 Model from a MySQL database and I have included both StoredProcedures and Tables.

    I know how to make regular instert/update/fetch/delete operations against the EF but I can't find my StoredProcedures.

    This was what I was hoping for:

    using (Entities context = new Entities())
    {
        context.MyStoreadProcedure(Parameters); 
    }
    

    Edit 1:

    This is how it looked without EF:

    sqlStr = "CALL updateGame(?,?,?,?,?,?,?)";
    
    commandObj = new OdbcCommand(sqlStr, mainConnection);
    commandObj.Parameters.Add("@id,", OdbcType.Int).Value = inGame.id;
    commandObj.Parameters.Add("@name", OdbcType.VarChar, 255).Value = inGame.name;
    commandObj.Parameters.Add("@description", OdbcType.Text).Value = ""; //inGame.description;
    commandObj.Parameters.Add("@yearPublished", OdbcType.DateTime).Value = inGame.yearPublished;
    commandObj.Parameters.Add("@minPlayers", OdbcType.Int).Value = inGame.minPlayers;
    commandObj.Parameters.Add("@maxPlayers", OdbcType.Int).Value = inGame.maxPlayers;
    commandObj.Parameters.Add("@playingTime", OdbcType.VarChar, 127).Value = inGame.playingTime;    
    
    return Convert.ToInt32(executeScaler(commandObj));
    

    PS. I can change EF version if needed

    Edit 1:

    CREATE DEFINER=`106228`@`%` PROCEDURE `updateGame`(
        inId INT,
        inName VARCHAR(255),
        inDescription TEXT,
        inYearPublished DATETIME,
        inMinPlayers INT,
        inMaxPlayers INT,
        inPlayingTime VARCHAR(127)
    )
    
  • Ivy
    Ivy over 11 years
    I dont get it, why should i hardcode the SP name? I have added them when generating the Model? Should thay not just be somewhere on the Context object as methods?
  • Ivy
    Ivy over 11 years
    I dont get it, why should i hardcode the SP name? I have added them when generating the Model? Should thay not just be somewhere on the Context object as methods?
  • Quinton Bernhardt
    Quinton Bernhardt over 11 years
    Yeah, this is the way to do it if you haven't linked it to your model and you want raw access ;)
  • Ivy
    Ivy over 11 years
    Tried this but it does not generate a method with parameters? Not sure how to putt in the parameters?
  • user1908061
    user1908061 over 11 years
    When the procedure has parameters, then they will be added.
  • ESG
    ESG over 11 years
    It does for me, using framework 4. Can you show the create statement of the procedure? (Only with the parameters)
  • ESG
    ESG over 11 years
    So, you don't have anything strange in there. It really should support parameters, I'm not sure why it's not. Can you try it with a procedure with only a few parameters, like 3 ints, see what it does?
  • Ivy
    Ivy over 11 years
    I tried to add one with only one parameter and its not working
  • Ivy
    Ivy over 11 years
    Thanks! Yes probalby, I will have to do this manually becouse I can´t update the MySQL server.
  • ESG
    ESG over 11 years
    You might be able to fix it by using a different version of your driver.
  • Admin
    Admin over 7 years
    This just executes the stored proc as non-query. It cannot read any returned tables
  • Admin
    Admin over 7 years
    You have to declare your ProyectoReporte class that represents the result table returned by query
  • Gert Arnold
    Gert Arnold almost 6 years
    Despite all the answers this is the only answer OP was looking for.