web-dev-qa-db-ja.com

ストアドプロシージャでDbContext.Database.SqlQuery <TElement>(sql、params)を使用する方法? EFコードファーストCTP5

私は3つのパラメータを持つストアドプロシージャを持っていて、結果を返すために以下を使用しようとしていました:

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

最初はSqlParameterオブジェクトをパラメータとして使用しようとしましたが、これはうまくいきませんでした。そして次のメッセージでSqlExceptionを投げました。

プロシージャーまたは関数 'mySpName'はパラメーター '@ param1'を予期していますが、指定されていません。

だから私の質問はあなたがパラメータを期待するストアドプロシージャでこのメソッドをどのように使うことができるかです。

ありがとう。

232
electricsheep

次の方法でSqlParameterインスタンスを提供する必要があります。

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

また、フォーマット指定子として "sql"パラメータを使用することができます。

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

この解決策はSQL Server 2005用の(のみ)です

皆さんは命の恩人ですが、@ Dan Morkが言ったように、ミックスにEXECを追加する必要があります。私をつまずかせたのは、

  • プロセス名の前の「EXEC」
  • Paramsの間にカンマ
  • Param Definitionsで '@'を切り落とします(ただし、ビットが必要かどうかはわかりません)。

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

//または

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

//または

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

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

//または

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

ほとんどの答えは、SPのパラメーターの順番に依存しているため、もろいです。 Stored Procのパラメータに名前を付けてパラメータ化された値をそれらに与えるほうがよい

SPの呼び出し時にパラメータの順序を気にせずに名前付きパラメータを使用するため

ExecuteStoreQueryおよびExecuteStoreCommandでSQL Serverの名前付きパラメータを使用する

最善のアプローチを説明します。 Dan Morkの答えよりも優れています。

  • 文字列の連結には依存せず、SPで定義されているパラメータの順序にも依存しません。

例えば。:

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)
4
Don Cheadle
db.Database.SqlQuery<myEntityType>("exec GetNewSeqOfFoodServing @p0,@p1,@p2 ", foods_WEIGHT.NDB_No, HLP.CuntryID, HLP.ClientID).Single()

または

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

または

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)

または

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

私はこの方法を使います。

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

GuidsとDatetimesをドロップするだけでSqlQueryが私のためにすべてのフォーマットを実行するので、私はそれが好きです。

2
Malcolm O'Hare

@Tom Halladayの答えは、あなたが買い物客にnull値もチェックし、paramsがnullの場合はDbNullableを送信するという言及で正しいです。

パラメータ化されたクエリ '...'は、パラメータ '@parameterName'を予期していますが、指定されていません。

このような何かが私を助けました

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

(このメソッドのクレジットは https://stackoverflow.com/users/284240/tim-schmelter になります)

それを次のように使います。

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

あるいは、もっと単純だが一般的ではない別の解決策は、

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

SELECTステートメントを使用して2つの入力パラメーターを受け取り、3つの値を返すストアード・プロシージャーを呼び出して作業していたときに同じエラー・メッセージが表示され、EFコード優先アプローチで以下のような問題を解決しました。

 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:SQL Server 2005でEXECキーワードがないと問題が発生しているようです。だから私は私の答えを更新し、次の行にEXECを追加したすべてのSQL Serverバージョンで動作するようにします。

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