Pregunta ¿Cómo llamar a los procedimientos almacenados con EntityFramework?


He generado un Modelo EF4 a partir de una base de datos MySQL y he incluido tanto StoredProcedures como Tables.

Sé cómo hacer operaciones regulares de inserción / actualización / búsqueda / eliminación contra el EF, pero no puedo encontrar mis procedimientos almacenados.

Esto era lo que esperaba:

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

Editar 1:

Así es como lucía sin 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));

PD. Puedo cambiar la versión EF si es necesario

Editar 1:

CREATE DEFINER=`106228`@`%` PROCEDURE `updateGame`(
    inId INT,
    inName VARCHAR(255),
    inDescription TEXT,
    inYearPublished DATETIME,
    inMinPlayers INT,
    inMaxPlayers INT,
    inPlayingTime VARCHAR(127)
)

31
2018-01-10 18:25


origen


Respuestas:


Una forma es usar la propiedad de la base de datos fuera de DbContext:

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

EF5 definitivamente lo admite.


59
2018-01-10 18:31



Ha utilizado la función SqlQuery e indica la entidad para mapear el resultado.

Le envío un ejemplo para realizar esto:

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();
}

8
2017-11-15 16:43



Una vez que su procedimiento almacenado se importa en su modelo, puede hacer clic con el botón derecho en él (desde el navegador modelo, en el Context.Store/Stored Procedures sección), y haga clic Add Function Import. Si necesita un tipo complejo como resultado, puede crearlo allí mismo.


4
2018-01-10 18:38



Básicamente, solo tiene que asignar el procedimiento a la entidad utilizando la asignación de procedimientos almacenados.

Una vez mapeado, utiliza el método habitual para agregar un elemento en EF y utilizará el procedimiento almacenado.

Por favor mira: Este enlace para un tutorial. El resultado será agregar una entidad como tal (que realmente usará su procedimiento almacenado)

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

            ctx.Students.Add(stud);
            ctx.SaveChanges();
        }

1
2018-01-19 10:38



Basado en la solicitud original de OP para poder llamar a un proceso almacenado como este ...

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

Pasajero sin sentido  tiene un proyecto que le permite llamar a un proceso almacenado desde el trabajo de marco de entidad como este ....

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>();
}

... y estoy trabajando en una marco de procedimiento almacenado (aquí) que puede llamar como en uno de mis métodos de prueba que se muestran a continuación ...

[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)
    {
    }
}

Si alguno de esos dos enfoques es bueno?


1
2017-08-30 08:15



Esto es lo que hice recientemente para mi aplicación de visualización de datos que tiene una base de datos SQL 2008. En este ejemplo, estoy recibiendo una lista devuelta por un procedimiento almacenado:

public List<CumulativeInstrumentsDataRow> GetCumulativeInstrumentLogs(RunLogFilter filter)
    {
        EFDbContext db = new EFDbContext();
        if (filter.SystemFullName == string.Empty)
        {
            filter.SystemFullName = null;
        }
        if (filter.Reconciled == null)
        {
            filter.Reconciled = 1;
        }
        string sql = GetRunLogFilterSQLString("[dbo].[rm_sp_GetCumulativeInstrumentLogs]", filter);
        return db.Database.SqlQuery<CumulativeInstrumentsDataRow>(sql).ToList();
    }

Y luego este método de extensión para algunos formatos en mi caso:

public string GetRunLogFilterSQLString(string procedureName, RunLogFilter filter)
        {
            return string.Format("EXEC {0} {1},{2}, {3}, {4}", procedureName, filter.SystemFullName == null ? "null" : "\'" + filter.SystemFullName + "\'", filter.MinimumDate == null ? "null" : "\'" + filter.MinimumDate.Value + "\'", filter.MaximumDate == null ? "null" : "\'" + filter.MaximumDate.Value + "\'", +filter.Reconciled == null ? "null" : "\'" + filter.Reconciled + "\'");

        }

0
2018-01-10 18:28



Este es un ejemplo de consultar el procedimiento MySQL utilizando Entity Framework

Esta es la definición de mi procedimiento almacenado en MySQL:

CREATE PROCEDURE GetUpdatedAds (
    IN curChangeTracker BIGINT
    IN PageSize INT
) 
BEGIN
   -- select some recored...
END;

Y así es como lo consulto usando Entity Framework:

 var curChangeTracker = new SqlParameter("@curChangeTracker", MySqlDbType.Int64).Value = 0;
 var pageSize = new SqlParameter("@PageSize", (MySqlDbType.Int64)).Value = 100;

 var res = _context.Database.SqlQuery<MyEntityType>($"call GetUpdatedAds({curChangeTracker}, {pageSize})");

Tenga en cuenta que estoy usando Interpolación de cadenas C # para construir mi Query String.


0
2018-05-12 02:21