c# - framework - ¿Cómo usar DbContext.Database.SqlQuery<TElement>(sql, params) con el procedimiento almacenado? Código EF primero CTP5
execute stored procedure in entity framework c# (9)
Tengo un procedimiento almacenado que tiene tres parámetros y he estado tratando de usar lo siguiente para devolver los resultados:
context.Database.SqlQuery<myEntityType>("mySpName", param1, param2, param3);
Al principio intenté usar objetos SqlParameter
como parámetros pero esto no funcionó y lancé una SqlException
con el siguiente mensaje:
El procedimiento o la función ''mySpName'' esperan el parámetro ''@ param1'', que no se suministró.
Entonces, mi pregunta es ¿cómo puede usar este método con un procedimiento almacenado que espera parámetros?
Gracias.
Además, puede usar el parámetro "sql" como un especificador de formato:
context.Database.SqlQuery<MyEntityType>("mySpName @param1 = {0}", param1)
Debe proporcionar las instancias de SqlParameter de la siguiente manera:
context.Database.SqlQuery<myEntityType>(
"mySpName @param1, @param2, @param3",
new SqlParameter("param1", param1),
new SqlParameter("param2", param2),
new SqlParameter("param3", param3)
);
La respuesta de @Tom Halladay es correcta con la mención de que también deberías buscar valores nulos y enviar DbNullable si los parámetros son nulos, ya que obtendrías una excepción como
La consulta parametrizada ''...'' espera el parámetro ''@parameterName'', que no se suministró.
Algo como esto me ayudó
public static object GetDBNullOrValue<T>(this T val)
{
bool isDbNull = true;
Type t = typeof(T);
if (Nullable.GetUnderlyingType(t) != null)
isDbNull = EqualityComparer<T>.Default.Equals(default(T), val);
else if (t.IsValueType)
isDbNull = false;
else
isDbNull = val == null;
return isDbNull ? DBNull.Value : (object) val;
}
(El crédito por el método va a https://.com/users/284240/tim-schmelter )
Entonces úsalo como:
new SqlParameter("@parameterName", parameter.GetValueOrDbNull())
u otra solución, más simple, pero no genérica sería:
new SqlParameter("@parameterName", parameter??(object)DBNull.Value)
Tuve el mismo mensaje de error cuando trabajaba para llamar a un procedimiento almacenado que toma dos parámetros de entrada y devuelve 3 valores con la instrucción SELECT y resolví el problema como se muestra a continuación en el Enfoque del Código EF Primer
SqlParameter @TableName = new SqlParameter()
{
ParameterName = "@TableName",
DbType = DbType.String,
Value = "Trans"
};
SqlParameter @FieldName = new SqlParameter()
{
ParameterName = "@FieldName",
DbType = DbType.String,
Value = "HLTransNbr"
};
object[] parameters = new object[] { @TableName, @FieldName };
List<Sample> x = this.Database.SqlQuery<Sample>("EXEC usp_NextNumberBOGetMulti @TableName, @FieldName", parameters).ToList();
public class Sample
{
public string TableName { get; set; }
public string FieldName { get; set; }
public int NextNum { get; set; }
}
ACTUALIZACIÓN : Parece que con SQL SERVER 2005 falta la palabra clave EXEC está creando problemas. Entonces, para permitir que funcione con todas las versiones del SERVIDOR SQL, actualicé mi respuesta y agregué EXEC en la siguiente línea
List<Sample> x = this.Database.SqlQuery<Sample>(" EXEC usp_NextNumberBOGetMulti @TableName, @FieldName", parameters).ToList();
Yo uso este método:
var results = this.Database.SqlQuery<yourEntity>("EXEC [ent].[GetNextExportJob] {0}", ProcessorID);
Me gusta porque acabo de pasar Guids and Datetimes y SqlQuery realiza todo el formato para mí.
Esta solución es (solo) para SQL Server 2005
Ustedes son salvavidas, pero como dijo @Dan Mork, necesitas agregar EXEC a la mezcla. Lo que me estaba tropezando era:
- ''EXEC'' antes del Nombre Proc
- Comas entre params
- Cortar ''@'' en las definiciones de parámetros (aunque no estoy seguro de que se requiera ese bit).
:
context.Database.SqlQuery<EntityType>(
"EXEC ProcName @param1, @param2",
new SqlParameter("param1", param1),
new SqlParameter("param2", param2)
);
La mayoría de las respuestas son frágiles porque dependen del orden de los parámetros del SP. Es mejor nombrar los parámetros de Stored Proc y darles valores parametrizados.
Para utilizar parámetros con nombre al llamar a su SP, sin preocuparse por el orden de los parámetros
Usando los parámetros nombrados de SQL Server con ExecuteStoreQuery y ExecuteStoreCommand
Describe el mejor enfoque. Mejor que la respuesta de Dan Mork aquí.
- No se basa en concatenar cadenas, y no se basa en el orden de los parámetros definidos en el SP.
P.ej:
var cmdText = "[DoStuff] @Name = @name_param, @Age = @age_param";
var params = new[]{
new SqlParameter("name_param", "Josh"),
new SqlParameter("age_param", 45)
};
context.Database.SqlQuery<myEntityType>(cmdText, params)
db.Database.SqlQuery<myEntityType>("exec GetNewSeqOfFoodServing @p0,@p1,@p2 ", foods_WEIGHT.NDB_No, HLP.CuntryID, HLP.ClientID).Single()
@ p0, @ p1, @ p2 ......
o
db.Database.SqlQuery<myEntityType>(
"exec GetNewSeqOfFoodServing @param1, @param2",
new SqlParameter("param1", param1),
new SqlParameter("param2", param2)
);
o
var cmdText = "exec [DoStuff] @Name = @name_param, @Age = @age_param";
var params = new[]{
new SqlParameter("name_param", "Josh"),
new SqlParameter("age_param", 45)
};
db.Database.SqlQuery<myEntityType>(cmdText, params)
o
db.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 });
//O
using(var context = new MyDataContext())
{
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
}
//O
using(var context = new MyDataContext())
{
object[] parameters = { param1, param2, param3 };
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
parameters).ToList();
}
//O
using(var context = new MyDataContext())
{
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
param1, param2, param3).ToList();
}