J'ai généré un modèle EF4 à partir d'une base de données MySQL et j'ai inclus à la fois StoredProcedures et Tables.
Je sais comment effectuer des opérations instert/update/fetch/delete régulières sur l'EF, mais je ne trouve pas mes procédures stockées.
C'était ce que j'espérais:
using (Entities context = new Entities())
{
context.MyStoreadProcedure(Parameters);
}
Modifier 1:
Voici à quoi cela ressemblait sans 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. Je peux changer la version EF si nécessaire
Modifier 1:
CREATE DEFINER=`106228`@`%` PROCEDURE `updateGame`(
inId INT,
inName VARCHAR(255),
inDescription TEXT,
inYearPublished DATETIME,
inMinPlayers INT,
inMaxPlayers INT,
inPlayingTime VARCHAR(127)
)
Une solution consiste à utiliser la propriété Database du DbContext:
SqlParameter param1 = new SqlParameter("@firstName", "Frank");
SqlParameter param2 = new SqlParameter("@lastName", "Borland");
context.Database.ExecuteSqlCommand("sp_MyStoredProc @firstName, @lastName",
param1, param2);
EF5 soutient définitivement cela.
Vous avez utilisé la fonction SqlQuery et indiqué l'entité pour mapper le résultat.
J'envoie un exemple pour effectuer ceci:
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();
}
Une fois votre procédure stockée importée dans votre modèle, vous pouvez cliquer dessus avec le bouton droit de la souris (à partir du navigateur de modèles, dans la section Context.Store
/Stored Procedures
), puis cliquer sur Add Function Import
. Si vous avez besoin d'un type complexe, vous pouvez le créer ici.
En gros, il vous suffit de mapper la procédure sur l'entité à l'aide du mappage de procédures stockées.
Une fois mappé, vous utilisez la méthode habituelle pour ajouter un élément dans EF et il utilisera votre procédure stockée à la place.
S'il vous plaît voir: Ce lien pour une procédure pas à pas . Le résultat sera l'ajout d'une entité comme so (qui utilisera réellement votre procédure stockée)
using (var ctx = new SchoolDBEntities())
{
Student stud = new Student();
stud.StudentName = "New sp student";
stud.StandardId = 262;
ctx.Students.Add(stud);
ctx.SaveChanges();
}
Basé sur la requête initiale de l'OP pour pouvoir appeler un proc stocké comme ceci ...
using (Entities context = new Entities())
{
context.MyStoreadProcedure(Parameters);
}
Passager sans âme a un projet qui vous permet d’appeler un proc stocké depuis un cadre de travail comme celui-ci ....
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>();
}
... et je travaille sur un framework de procédures stockées ( ici ) que vous pouvez appeler comme dans l'une de mes méthodes de test ci-dessous ...
[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 l'une ou l'autre de ces deux approches est-elle bonne?
C'est ce que j'ai récemment fait pour mon application de visualisation de données qui dispose d'une base de données SQL 2008 Dans cet exemple, je reçois une liste renvoyée par une procédure stockée:
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();
}
Et puis cette méthode d'extension pour un formatage dans mon cas:
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 + "\'");
}
Ceci est un exemple d'interrogation de procédure MySQL avec Entity Framework
Voici la définition de ma procédure stockée dans MySQL:
CREATE PROCEDURE GetUpdatedAds (
IN curChangeTracker BIGINT
IN PageSize INT
)
BEGIN
-- select some recored...
END;
Et voici comment je l'interroge en utilisant 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})");
Notez que j'utilise C # String Interpolation pour construire ma chaîne de requête.