web-dev-qa-db-ja.com

Entity Framework 4.0 / .edmxを使用してC#からスカラー関数を呼び出す

スカラー関数を.edmxにマップしたいのですが、失敗します。エンティティフレームワークマッピングを右クリックし、データベースからモデルの更新を選択します。モデルブラウザのストアドプロシージャフォルダに表示されます。

ただし、モデルブラウザーのFunction Importsフォルダーに追加したい場合、メッセージスカラー関数が表示されませんドロップに表示されますダウンリスト。誰かが私を助けてくれますか?

次のような古い方法を使用してスカラー関数を呼び出すことができます。

dbContext.ExecuteStoreQuery<DateTime?>(
"SELECT dbo.getMinActualLoadDate ({0}, {1}, {2}) AS MyResult", 
LoadPkid, LoadFkStartLoc, TripSheetPkid).First();

しかし、それは最善の方法ではありません。前のコードの代わりに次のコードを使用してスカラー関数を呼び出すことができるように、マネージャーはスカラー関数を「関数インポート」フォルダーに配置できる方法を求めています。

dbContext.ExecuteFunction("getMinActualLoadDate ", paramList);

画像を追加して意味を表示しようとしましたが、評判がまだ低いため、表示できません。ただし、画像はここにあります: http://social.msdn.Microsoft.com/Forums/en-US/adodotnetentityframework/thread/756865e5-ff25-4f5f-aad8-fed9d741c05d

ありがとう。

21
jay

同じ問題が発生しました。そして、これは私が自分自身が十分に適しているとわかった解決策です(EF5でテストされましたが、EF4でも動作するはずです):

スカラー値関数をそのままの状態でマッピングすることはサポートされていませんが、直接実行できます。

Edmxファイルを編集して、edmxがスカラー値関数の適切なメソッドを生成するようにすることもできますが、データベースとモデルを同期する場合は削除されます。

スカラー値の関数実装を自分で記述します:

string sqlQuery = "SELECT [dbo].[CountMeals] ({0})";
Object[] parameters = { 1 };
int activityCount = db.Database.SqlQuery<int>(sqlQuery, parameters).FirstOrDefault();

またはedmxを編集し、スカラー値関数のカスタムマッピング用のXmlを追加します:

<Function Name="CountActivities" Aggregate="false" BuiltIn="false"    NiladicFunction="false" IsComposable="false"   ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
    <CommandText>
        SELECT [dbo].[CountActivities] (@personId)
    </CommandText>
    <Parameter Name="personId" Type="int" Mode="In" />
</Function>

この情報はこれで見つかりました ブログ投稿

15

これは、この問題に対する私の解決策です。これは、マネージャーが求めていたものとほぼ同じです。

バニラ法として:

    /// <summary>
    /// Calls a given Sql function and returns a singular value
    /// </summary>
    /// <param name="db">Current DbContext instance</param>
    /// <typeparam name="T">CLR Type</typeparam>
    /// <param name="sql">Sql function</param>
    /// <param name="parameters">Sql function parameters</param>
    /// <param name="schema">Owning schema</param>
    /// <returns>Value of T</returns>
    public T SqlScalarResult<T>(DbContext db, 
                                string sql, 
                                SqlParameter[] parameters,
                                string schema = "dbo") {

        if (string.IsNullOrEmpty(sql)) {
            throw new ArgumentException("function");
        }

        if (parameters == null || parameters.Length == 0) {
            throw new ArgumentException("parameters");
        }

        if (string.IsNullOrEmpty(schema)) {
            throw new ArgumentException("schema");
        }

        string cmdText =
            $@"SELECT {schema}.{sql}({string.Join(",",
                parameters.Select(p => "@" + p.ParameterName).ToList())});";

        // ReSharper disable once CoVariantArrayConversion
        return db.Database.SqlQuery<T>(cmdText, parameters).FirstOrDefault();

    }

}

そして、EFへの拡張メソッドとして:

namespace System.Data.Entity {

    public static class DatabaseExtensions {

        /// <summary>
        /// Calls a given Sql function and returns a singular value
        /// </summary>
        /// <param name="db">Current DbContext instance</param>
        /// <typeparam name="T">CLR Type</typeparam>
        /// <param name="sql">Sql function</param>
        /// <param name="parameters">Sql function parameters</param>
        /// <param name="schema">Owning schema</param>
        /// <returns>Value of T</returns>
        public static T SqlScalarResult<T>(this Database db, 
                                           string sql, 
                                           SqlParameter[] parameters,
                                           string schema = "dbo") {

            if (string.IsNullOrEmpty(sql)) {
                throw new ArgumentException("sql");
            }

            if (parameters == null || parameters.Length == 0) {
                throw new ArgumentException("parameters");
            }

            if (string.IsNullOrEmpty(schema)) {
                throw new ArgumentException("schema");
            }

            string cmdText =
                $@"SELECT {schema}.{sql}({string.Join(",", 
                    parameters.Select(p => "@" + p.ParameterName).ToList())});";

            // ReSharper disable once CoVariantArrayConversion
            return db.SqlQuery<T>(cmdText, parameters).FirstOrDefault();

        }

    }

}

ここでは喫煙しませんが、本格的な使用の前に単体テストをお勧めします。

7
dperish

唯一の解決策は、関数スカラー型をテーブル内の単一の値を持つテーブル値型に変換することです。コードサンプルを参照してください。

EDMX XMLで何も変更する必要はありません。SQL関数を変更してください

機能しないスカラー関数

CREATE FUNCTION [dbo].[GetSha256]
(
    -- Add the parameters for the function here
    @str nvarchar(max)
)
RETURNS VARBINARY(32)
AS
BEGIN
    RETURN ( SELECT * FROM HASHBYTES('SHA2_256', @str) AS HASH256 );
END -- this doesn't work.

スカラー関数->テーブル値関数に変換され、機能します

CREATE FUNCTION [dbo].[GetSha2561]
(
    -- Add the parameters for the function here
    @str nvarchar(max)
)
RETURNS  @returnList TABLE (CODE varbinary(32))
AS
BEGIN

    INSERT INTO @returnList
    SELECT HASHBYTES('SHA2_256', @str);

    RETURN; -- This one works like a charm.

END

Edmxスクリーンショット

enter image description here

1

Edit Function Import ダイアログ、ここで複合型を生成できます。探検してみてください。

enter image description here

scalarsの作成に成功したら、次のようにナビゲートできます

using (var con = new DatabaseEntities())
{
   long? invoiceNo = con.sp_GetInvoiceMaxNumber(code.Length + 2).First();
   ....
}
1
spajce

ページ内のコード:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        using (MayEntities context = new MayEntities())
        {
            string str = context.Database.SqlQuery<string>("select dbo.HeyYou()").Single().ToString();
            Response.Write(str); //output:'Hey this works'
        }
    }
}

スカラー関数:

CREATE FUNCTION [dbo].[HeyYou] ()
RETURNS varchar(20)
AS
BEGIN
    RETURN 'Hey this works'
END
go
0
sachin