web-dev-qa-db-fra.com

Comment utiliser DbContext.Database.SqlQuery <TElement> (sql, params) avec une procédure stockée? Code EF First CTP5

J'ai une procédure stockée qui a trois paramètres et j'ai essayé d'utiliser les éléments suivants pour renvoyer les résultats:

context.Database.SqlQuery<myEntityType>("mySpName", param1, param2, param3);

Au début, j’ai essayé d’utiliser des objets SqlParameter comme paramètres mais cela n’a pas fonctionné et jette un SqlException avec le message suivant:

La procédure ou la fonction 'mySpName' attend le paramètre '@ param1', qui n'a pas été fourni.

Ma question est donc la suivante: comment utiliser cette méthode avec une procédure stockée qui attend des paramètres?

Merci.

234
electricsheep

Vous devez fournir les instances SqlParameter de la manière suivante:

context.Database.SqlQuery<myEntityType>(
    "mySpName @param1, @param2, @param3",
    new SqlParameter("param1", param1),
    new SqlParameter("param2", param2),
    new SqlParameter("param3", param3)
);
366
Devart

De plus, vous pouvez utiliser le paramètre "sql" comme spécificateur de format:

context.Database.SqlQuery<MyEntityType>("mySpName @param1 = {0}", param1)
123
Dan Mork

Cette solution est (uniquement) pour SQL Server 2005

Vous êtes des sauveteurs, mais comme l'a dit @Dan Mork, vous devez ajouter EXEC au mélange. Ce qui me faisait trébucher était:

  • 'EXEC' avant le nom du proc
  • Virgules entre les paramètres
  • Découper "@" dans les définitions de paramètres (vous n'êtes pas sûr que ce bit est requis).

:

context.Database.SqlQuery<EntityType>(
    "EXEC ProcName @param1, @param2", 
    new SqlParameter("param1", param1), 
    new SqlParameter("param2", param2)
);
71
Tom Halladay
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 });

//Ou

using(var context = new MyDataContext())
{
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
}

//Ou

using(var context = new MyDataContext())
{
object[] parameters =  { param1, param2, param3 };

return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
parameters).ToList();
}

//Ou

using(var context = new MyDataContext())
{  
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
param1, param2, param3).ToList();
}
13
Thulasiram

La plupart des réponses sont fragiles car elles dépendent de l'ordre des paramètres du SP. Mieux vaut nommer les paramètres de Stored Proc et leur donner des valeurs paramétrées.

Pour utiliser les paramètres nommés lors de l'appel de votre SP, sans vous soucier de l'ordre des paramètres

tilisation de paramètres nommés SQL Server avec ExecuteStoreQuery et ExecuteStoreCommand

Décrit la meilleure approche. Mieux que la réponse de Dan Mork ici.

  • Ne repose pas sur la concaténation de chaînes ni sur l'ordre des paramètres définis dans le SP.

Par exemple.:

var cmdText = "[DoStuff] @Name = @name_param, @Age = @age_param";
var sqlParams = new[]{
   new SqlParameter("name_param", "Josh"),
   new SqlParameter("age_param", 45)
};

context.Database.SqlQuery<myEntityType>(cmdText, sqlParams)
5
Don Cheadle
db.Database.SqlQuery<myEntityType>("exec GetNewSeqOfFoodServing @p0,@p1,@p2 ", foods_WEIGHT.NDB_No, HLP.CuntryID, HLP.ClientID).Single()

ou

db.Database.SqlQuery<myEntityType>(
    "exec GetNewSeqOfFoodServing @param1, @param2", 
    new SqlParameter("param1", param1), 
    new SqlParameter("param2", param2)
);

ou

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)

ou

db.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
3
Hossein Hajizadeh

J'utilise cette méthode:

var results = this.Database.SqlQuery<yourEntity>("EXEC [ent].[GetNextExportJob] {0}", ProcessorID);

Je l’aime bien parce que je viens de déposer dans Guids et Datetimes et que SqlQuery effectue tout le formatage pour moi.

2
Malcolm O'Hare

La réponse de @Tom Halladay est correcte avec la mention que vous voulez également vérifier les valeurs nulles et envoyer DbNullable si les paramètres sont nuls, comme vous obtiendrez une exception comme

La requête paramétrée '...' attend le paramètre '@parameterName' qui n'a pas été fourni.

Quelque chose comme ça m'a aidé

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

(le crédit pour la méthode va à https://stackoverflow.com/users/284240/tim-schmelter )

Alors utilisez-le comme:

new SqlParameter("@parameterName", parameter.GetValueOrDbNull())

ou une autre solution, plus simple, mais non générique serait:

new SqlParameter("@parameterName", parameter??(object)DBNull.Value)
1
emanuel.virca

J'avais le même message d'erreur lorsque je travaillais avec l'appel d'une procédure stockée qui prend deux paramètres d'entrée et renvoie 3 valeurs à l'aide de l'instruction SELECT et j'ai résolu le problème comme ci-dessous dans EF Code First Approach

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

UPDATE: Il semble qu'avec SQL SERVER 2005, le mot clé EXEC manquant crée un problème. Donc, pour lui permettre de fonctionner avec toutes les versions de SQL SERVER, j'ai mis à jour ma réponse et ajouté EXEC en dessous de la ligne

 List<Sample> x = this.Database.SqlQuery<Sample>(" EXEC usp_NextNumberBOGetMulti @TableName, @FieldName", param).ToList();
0
Ziggler