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


250

3つのパラメーターを持つストアード・プロシージャーがあり、以下を使用して結果を返そうとしています。

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

最初にSqlParameterオブジェクトをパラメーターとして使用しようとしましたが、これは機能せずSqlException、次のメッセージでをスローしました。

プロシージャまたは関数 'mySpName'には、パラメータ '@ param1'が必要ですが、指定されていません。

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

ありがとう。


SQL Serverのどのバージョンを使用していますか?2008で互換(90)モードで動作するコードに問題がありますが、2005に対して実行すると、構文エラーで失敗します。
ガット

4
@Gats-SQL 2005でも同じ問題が発生しました。ストアドプロシージャ名の前に「EXEC」を追加してください。私は、将来の参考のためにここにこの情報を掲示:stackoverflow.com/questions/6403930/...
ダン・モルク

回答:


389

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

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

3
このメソッドをnull許容型でどのように機能させますか?null許容の小数でこれを試しましたが、小数がnullの場合、パラメーターがないというエラーが表示されます。ただし、@ DanMorkで言及されている以下の方法は機能します。
ポールジョンソン

2
DbNull.Valuenullの代わりに渡すことで問題は解決しますか?
Alireza

29
\ @ p#構文を使用して、context.Database.SqlQuery <myEntityType( "mySpName \ @ p0、\ @ p1、\ @ p2"、param1、param2、param3)のようにSqlParameterを使用しないようにすることもできます。ソース:msdn.microsoft.com/en-US/data/jj592907。(注:ユーザー通知を避けるために\ @を使用する必要があり、バックスラッシュなしで読む必要があります。)
Marco

3
DateTimeパラメータを使用している場合は、名前と値だけでなく、パラメータタイプも指定する必要があります。例:dbContext.Database.SqlQuery <Invoice>( "spGetInvoices @dateFrom、@dateTo"、new SqlParameter {ParameterName = "dateFrom"、SqlDbType = SqlDbType.DateTime、Value = startDate}、new SqlParameter {ParameterName = "dateTo"、 SqlDbType = SqlDbType.DateTime、Value = endDate}); 別の重要なことは、パラメータの順序を尊重することです。
フランシスコゴールデンスタイン2014

あなたは親切に私はあなたがguidlineに従う必要があり、間違ったが、全く効果がやっているものを確認することができますstackoverflow.com/questions/27926598/...
有毒

129

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

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

これに賛成票を投じなければなりませんでした。回答としては受け入れられませんでしたが、回答として選択したものよりもはるかに簡単にソリューションを作成できます。
12

10
この構文は少し気になります。SQLインジェクションの影響を受けますか?私はEFが「EXEC mySpName @ Param1 =」を実行していると想定しますが、「x 'GO [悪意のあるスクリプト]」を送信して問題を引き起こす可能性はありますか?
トム・ハラディ

10
@TomHalladay SQLインジェクションのリスクはありません-メソッドは、@スタイルのパラメーターと同じように、タイプに基づいてパラメーターを引用し、エスケープします。したがって、文字列パラメータの場合は、ステートメントに引用符なしで「SELECT * FROM Users WHERE email = {0}」を使用します。
ロスマクナブ2013

私の場合、SPには多くのオプションパラメータがあり、SqlParametersでの呼び出しは機能しませんでしたが、この形式でうまくいきます。最初に「EXEC」を追加する必要がありました。ありがとう。
Onur Topal 2013

1
この回答は、オプションのパラメーターを使用してprocにパラメーターを指定する必要がある場合に役立ちます。機能しないProcName @optionalParam1 = @opVal1, @optionalParam2 = @opVal2 例:機能する例:ProcName @optionalParam1 = {0}, @optionalParam2 = {1}
Garrison Neely

72

このソリューションは(のみ)SQL Server 2005用です

あなたたちはライフセーバーですが、@ Dan Morkが言ったように、ミックスにEXECを追加する必要があります。私をつまずかせていたのは:

  • プロシージャ名の前の「EXEC」
  • パラメータ間のコンマ
  • パラメータ定義の「@」を切り落とします(ただし、そのビットが必要かどうかはわかりません)。

context.Database.SqlQuery<EntityType>(
    "EXEC ProcName @param1, @param2", 
    new SqlParameter("param1", param1), 
    new SqlParameter("param2", param2)
);

21
+1。投票数の多い回答にはは含まれていませんが、除外するとexec例外が発生することを確認できます。
ジョーダングレイ

ありがとう、エラーが発生しました、EXECを追加しましたが、エラーはなくなりました。変な部分は、context.Database.SqlQuery <EntityType>( "ProcName '" + param1 + "'、 '" + param2 + "'");を実行した場合です。機能しましたが、パラメーターを追加した場合、EXECキーワードを追加するまで機能しませんでした。
ソルミード2014年

2
参考:execキーワードは必要ありません。+1はparamsの@を削除するため、常に混乱を招きます。
Nathan Koop、2014年

+ 1、EXECが欠落していて、次のメッセージでSqlExceptionsが発生し続けました: 'procName'の近くに不正な構文があります。
A.マレー

1
@Zigglerは2005年以降ですか?EXECキーワードは、主に2005年に逆行して、私たちのそれらのための課題となっている
トム・ハラディ

15
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();
}

Assembly EntityFramework.dll、v4.4.0.0
Thulasiram

2
using(var context = new MyDataContext())を使用している場合、.ToList()は必須です。
Thulasiram 2012年

正しい結果セットを取得するには.ToList()が必須であることを発見するために、かなりの時間を費やしました。
Halim

8

ほとんどの回答は、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)

「params」は予約されているキーワードのようですので、そのようには使えないと思います。それ以外の場合、これは私にとって役立つ回答でした。ありがとう!
ooXei1sh

@ ooXei1sh-修正、sqlParams変数を使用
Don Cheadle

予約語を使用するために、@を前に付けることができますが、実際にはそうしないでください
StingyJack

6
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とDatetimeを追加するだけで、SqlQueryがすべての書式設定を実行してくれるので、気に入っています。


1

@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)

0

2つの入力パラメーターを受け取り、SELECTステートメントを使用して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; }
}

更新:SQL SERVER 2005でEXECキーワードが欠落していると問題が発生しているようです。したがって、それがすべてのSQL SERVERバージョンで機能するように、私は私の答えを更新し、以下の行にEXECを追加しました

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

以下のリンクをご覧ください。exec msdn.microsoft.com/en-us/data/jj592907.aspx
Ziggler

0

私はこのようにEF 6.xを使って採掘しました:

using(var db = new ProFormDbContext())
            {
                var Action = 1; 
                var xNTID = "A239333";

                var userPlan = db.Database.SqlQuery<UserPlan>(
                "AD.usp_UserPlanInfo @Action, @NTID", //, @HPID",
                new SqlParameter("Action", Action),
                new SqlParameter("NTID", xNTID)).ToList();


            }

sqlparameterを2倍にしないでください。これを行うと、変数に火傷を負う人がいます。

var Action = new SqlParameter("@Action", 1);  // Don't do this, as it is set below already.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.