c# - sqlquery - mapear stored procedure entity framework
¿Cómo llamar a los procedimientos almacenados con EntityFramework? (7)
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();
}
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)
)
Basado en la solicitud original de OP para poder llamar a un proceso almacenado como este ...
using (Entities context = new Entities())
{
context.MyStoreadProcedure(Parameters);
}
El pasajero sin mente 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 un marco de procedimientos almacenados ( aquí ) al que puedes 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?
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 utilizando C # String Interpolation para construir mi Query String.
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 + "/'");
}
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();
}
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.
Una vez que su procedimiento almacenado se importa en su modelo, puede hacer clic con el botón derecho en él (desde el navegador de modelos, en la sección Stored Procedures
/ Stored Procedures
) y hacer clic en Add Function Import
. Si necesita un tipo complejo como resultado, puede crearlo allí mismo.