I\'ve got the latest Mysql connector that allows you to use the Visual Studio Entity Framework designer. It\'s been working great, but I just added a stored proc.
I like this parameter approach more secure as it can handle the sql injection problems as well. I made it generalized as follows with :
public DbRawSqlQuery<T> ExecuteStoredProcedure<T>(string storedProcedureName, params object[] parameters)
{ string storedProcedureCommand = "CALL " + storedProcedureName + "(";
List<object> augmentedParameters = parameters.ToList();
MySqlParameter[] queryParams;
storedProcedureCommand = AddParametersToCommand(storedProcedureCommand, augmentedParameters, out queryParams);
storedProcedureCommand += ");";
return ((DbContext)this).Database.SqlQuery<T>(storedProcedureCommand, queryParams);
}
private string AddParametersToCommand(string storedProcedureCommand, List<object> augmentedParameters, out MySqlParameter[] queryParams)
{
string paramName = "";
queryParams = new MySqlParameter[augmentedParameters.Count()];
for (int i = 0; i < augmentedParameters.Count(); i++)
{
paramName = "p" + i;
queryParams[i] = new MySqlParameter(paramName,augmentedParameters[i]);
storedProcedureCommand += "@" + paramName;
if (i < augmentedParameters.Count - 1)
{
storedProcedureCommand += ",";
}
}
return storedProcedureCommand;
}
In case you find this helpful, here is the approach I use for working with stored procedures with parameters in MySQL from the MySQL Connector/.NET Entity Framework provider. I call ExecuteStoreQuery(). This liberates me from having to deal with the challenges of mapping procedures with parameters in the model. This works for our needs.
public IList<SearchResultsMember> SearchMembers(int memberID, string countryCode, string regionCode, string cityCode, float distanceKm,
int genderID, int ageMin, int ageMax, int offsetRowIndex, int maxRows)
{
MySqlParameter[] queryParams = new MySqlParameter[] {
new MySqlParameter("memberIDParam", memberID),
new MySqlParameter("countryCodeParam", countryCode),
new MySqlParameter("regionCodeParam", regionCode),
new MySqlParameter("cityCodeParam", cityCode),
new MySqlParameter("distanceKmParam", distanceKm),
new MySqlParameter("genderIDParam", genderID),
new MySqlParameter("ageMinParam", ageMin),
new MySqlParameter("ageMaxParam", ageMax),
new MySqlParameter("offsetRowIndexParam", offsetRowIndex),
new MySqlParameter("maxRowsParam", maxRows)
};
StringBuilder sb = new StringBuilder();
sb.Append("CALL search_members(@memberIDParam, @countryCodeParam, @regionCodeParam, @cityCodeParam, @distanceKmParam, @genderIDParam, @ageMinParam, @ageMaxParam, @offsetRowIndexParam, @maxRowsParam)");
string commandText = sb.ToString();
var results = _context.ExecuteStoreQuery<SearchResultsMember>(commandText, queryParams);
return results.ToList();
}
It was my solution to call a stored procedure. I hope usefull.
MovieDbEntities db = new MovieDbEntities();
int id = 2;
var result = db.Movie.SqlQuery($"CALL SP_ReadMovie({id})").ToList();
Here is a little extension we did for doing StoredProcedures on our DbContext:
public static List<T> ExecuteStoredProcedure<T>(this DbContext dbContext, string storedProcedureName, params object[] parameters)
{
string storedProcedureCommand = "CALL " + storedProcedureName + "(";
List<object> augmentedParameters = parameters.ToList();
storedProcedureCommand = AddParametersToCommand(storedProcedureCommand, augmentedParameters);
storedProcedureCommand += ");";
return dbContext.Database.SqlQuery<T>(storedProcedureCommand).ToList<T>();
}
public static List<T> ExecuteStoredRecursiveProcedure<T>(this DbContext dbContext, string storedProcedureName, params object[] parameters)
{
string storedProcedureCommand = "SET max_sp_recursion_depth = " + maxRecursionCount + "; CALL " + storedProcedureName + "(";
List<object> augmentedParameters = parameters.ToList();
storedProcedureCommand = AddParametersToCommand(storedProcedureCommand, augmentedParameters);
storedProcedureCommand += ");";
return dbContext.Database.SqlQuery<T>(storedProcedureCommand).ToList<T>();
}
private static string AddParametersToCommand(string storedProcedureCommand, List<object> augmentedParameters)
{
for (int i = 0; i < augmentedParameters.Count(); i++)
{
storedProcedureCommand = AddParameterToCommand(storedProcedureCommand, augmentedParameters, i);
}
return storedProcedureCommand;
}
private static string AddParameterToCommand(string storedProcedureCommand, List<object> augmentedParameters, int i)
{
if (augmentedParameters[i].GetType() == typeof(string))
{
storedProcedureCommand += "'";
}
storedProcedureCommand += (augmentedParameters[i].ToString());
if (augmentedParameters[i].GetType() == typeof(string))
{
storedProcedureCommand += "'";
}
if (i < augmentedParameters.Count - 1)
{
storedProcedureCommand += ",";
}
return storedProcedureCommand;
}
Also note one most important thing when dealing with mysql database; always name the stored procedures parameters differently with the table column names otherwise its mixed up in the query inside the sp.
For example:
CREATE PROCEDURE `authenticate_user`(
IN p_login_name varchar(50),
IN p_password varchar(80)
)
BEGIN
SELECT `user`.`user_id`,
`user`.`login_name`,
`user`.`password`
from users
where `login_name` = p_login_name
and `password` = p_password;
END
Here is a sample of my code got it working with VS2012 and Mysql connector 6.8.3 just generate your datamodel same as usual and dont forget to include the stored procedures.
Hope this help's someone.
public static IList<MyClass> GetCustOrderHist(string someParameter)
{
IList<MyClass> data = ((IObjectContextAdapter)TestDashboardEntities).ObjectContext.ExecuteStoreQuery<MyClass>("CALL CustOrderHist({0});", someParameter).ToList();
return data;
}
public class MyClass
{
public string ProductName { get; set; }
public int TOTAL { get; set; }
}