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




ado.net linq-to-entities entity-framework-ctp5 (9)

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

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

最初は、 SqlParameterオブジェクトをparamsとして使用しようとしSqlParameterが、これはうまくいかず、 SqlExceptionれました。次のメッセージが表示されます。

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

だから私の質問は、パラメータを期待するストアドプロシージャでこのメソッドを使用する方法ですか?

ありがとう。


Answers

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

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

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

最良のアプローチについて説明します。 ここのDan Morkの答えよりも良い。

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

例えば:

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 ......
または

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

また、 "sql"パラメータを書式指定子として使用することもできます。

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

@ Tom Halladayの答えは、あなたがshopuldで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://.com/users/284240/tim-schmelter送られhttps://.com/users/284240/tim-schmelter )

次に、次のように使用します。

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

よりシンプルですが一般的なものではないでしょう:

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

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

皆さんはライフセーバーですが、@Dan Mork氏によると、EXECをミックスに追加する必要があります。 私をひっくり返していたのは、

  • Proc Nameの前の 'EXEC'
  • Params間のカンマ
  • Param Definitionsの '@'を切り捨てます(ただし、ビットが必要です)。

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

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

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

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

// Or

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

// Or

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

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

// Or

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

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

更新 :EXECキーワードが見つからないSQL SERVER 2005の問題が発生しているようです。 だからそれはすべてのSQL Serverのバージョンで動作するように私の答えを更新し、下の行でEXECを追加

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

Configuration.AddAssembly()メソッドで間違ったアセンブリを追加していたため、同じ問題が発生しました。





c# sql ado.net linq-to-entities entity-framework-ctp5