Entity Framework Code Firstはストアドプロシージャをサポートしていますか?


112

私はEFコードファーストのプレゼンテーションをいくつか見てきましたが、EFCFがストアドプロシージャでどのように機能するかは知りませんでした。

spを使用するメソッドを宣言するにはどうすればよいですか?エンティティのプロパティを手動でspパラメータにマッピングせずに、spを呼び出すメソッドにエンティティを渡すことはできますか?

また、モデルを変更するとどうなりますか?モデルからテーブルを再作成しているときにspをドロップしますか?そしてトリガーはどうですか?

これらがサポートされていない場合、将来的にサポートする予定はありますか?


5
EFロードマップは、EF 6がコードファーストのストアドプロシージャと関数をサポートすることを示しています。entityframework.codeplex.com/wikipage?title=ロードマップ
フレンキー

回答:


66

編集: EF4.1(下)に対する私の元の回答は現在古くなっています。マイクロソフトのEFチームで働くDiego Vegaからの以下の回答をご覧ください。


@gsharpとShawn Mclean:この情報はどこで入手できますか?基になるObjectContextにまだアクセスできませんか?

IEnumerable<Customer> customers = 
    ((IObjectContextAdapter)this)
    .ObjectContext.ExecuteStoreQuery<Customer>("select * from customers");

「select」ステートメントをストアドプロシージャに置き換えれば、完了です。

あなたの他の質問については:はい、残念ながらあなたのspは壊れてしまいます。コードに「CREATE PROCEDURE」ステートメントを追加する必要がある場合があります。

EF 4.2の場合:

var customers = context.Database.SqlQuery<Customer>("select * from customers")

ありがとう。この件に関する詳細情報が記載されているリンクをいくつか紹介してください。
フレンキー、2011年

1
ObjectContextオブジェクトの3つの実行関数(ExecuteStoreQuery、ExecuteFunction、およびExecuteStoreCommand)を調べます。
anon

その質問を誤解した。私は、彼がSPの最初のコードを最初に作成したいと考えていました。
gsharp 2011年

Context.OnModelCreatingをオーバーライドし、カスタムロジックを追加して、コードを介してストアドプロシージャなどのデータベースアイテムをかなり簡単に作成できます。理想的ではありませんが、ピンチでそれがうまくいきます。
Rick Strahl

IObjectContextAdapterキャストは必要ありません。DbContextは、組み込みのDatabaseオブジェクトを使用して、spまたはカスタムSQLステートメントを処理できます。context.Database.SqlQuery <Dummy>( "sp_GetDummy");
Steven K.

50

更新: EF6以降、EFコードファーストは挿入、更新、削除のストアドプロシージャマッピングをサポートしています。MapToStoredProceduresメソッドを使用して、モデルの作成中にストアドプロシージャのマッピングを指定できます。また、これらの操作の基本的なストアドプロシージャの自動足場もサポートしています。こちらの機能仕様をご覧ください

元の回答: 最初のリリースでは、Code-Firstのモデルでのストアドプロシージャのマッピングはサポートされません。また、タイプからCRUD操作のストアドプロシージャを自動的に生成する方法もありません。これらは、今後追加したい機能です。

このスレッドで言及したように、ObjectContextにフォールバックすることは可能ですが、DbContextは、ネイティブSQLクエリおよびコマンド(DbSet.SqlQuery、DbContext.Database.SqlQuery、DbContext.Database.ExecuteSqlCommandなど)を実行するための素晴らしいAPIも提供します。異なるSqlQueryバージョンには、EF4に存在するのと同じ基本的な具体化機能があります(ExecuteStoreQuery:http ://msdn.microsoft.com/en-us/library/dd487208.aspxなど)。

お役に立てれば。


6
:ところで、私は詳細がどのように、ストアドプロシージャを呼び出すために、出力パラメータを持つストアドプロシージャにも、これらのメソッドを使用することを数日前にポストのブログを書いたblogs.msdn.com/b/diego/archive/2012/01/10/...を
divega 2012年

3
2013年後半、EF6はまだ開発中です。sprocsのサポートを改善するためだけに3年待っています、ため息。
DOK

1
@divegaストアドプロシージャから値を選択するための厳密に型指定されたサポートはありますか?このコードファーストのアプローチは、オブジェクトのライフタイムの管理に固有のように見えますか?具体的には、TotalRows出力パラメーターでspFooSearchストアドプロシージャを使用して、複雑な検索を行います。
John Zabroski、2014年

31
    public IList<Product> GetProductsByCategoryId(int categoryId)
    {
        IList<Product> products;

        using (var context = new NorthwindData())
        {
            SqlParameter categoryParam = new SqlParameter("@categoryID", categoryId);
            products = context.Database.SqlQuery<Product>("Products_GetByCategoryID @categoryID", categoryParam).ToList();
        }

        return products;
    }

    public Product GetProductById(int productId)
    {
        Product product = null;

        using (var context = new NorthwindData())
        {
            SqlParameter idParameter = new SqlParameter("@productId", productId);
            product = context.Database.SqlQuery<Product>("Product_GetByID @productId", idParameter).FirstOrDefault();
        }

        return product;
    }

8

よりタイプセーフなソリューションは次のようになります。

http://strugglesofacoder.blogspot.be/2012/03/calling-stored-procedure-with-entity.html

このクラスの使用法は次のとおりです。

var testProcedureStoredProcedure = new TestProcedureStoredProcedure() { Iets = 5, NogIets = true };

var result = DbContext.Database.ExecuteStoredProcedure(testProcedureStoredProcedure);

リンクは、もはや有効ではありませんが、ここでのアーカイブです:web.archive.org/web/20150430090848/http://www.lucbos.net/2012/...
アルトゥーロ・トレス・サンチェス

2

.NET Core(EntityFrameworkCore)の場合、私はそれらを動作させることができました。

最も卑劣ではないかもしれませんが、これは間違いなく機能します。

ストアドプロシージャを追加するための移行は次のようになります

using Microsoft.EntityFrameworkCore.Migrations;
using System.Text;

namespace EFGetStarted.AspNetCore.NewDb.Migrations
{
    public partial class StoredProcedureTest : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("CREATE PROCEDURE GetBlogForAuthorName");
            sb.AppendLine("@authorSearch varchar(100)");
            sb.AppendLine("AS");
            sb.AppendLine("BEGIN");
            sb.AppendLine("-- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.");
            sb.AppendLine("SET NOCOUNT ON;");
            sb.AppendLine("SELECT  Distinct Blogs.BlogId, Blogs.Url");
            sb.AppendLine("FROM Blogs INNER JOIN");
            sb.AppendLine("Posts ON Blogs.BlogId = Posts.BlogId INNER JOIN");
            sb.AppendLine("PostsAuthors ON Posts.PostId = PostsAuthors.PostId Inner JOIN");
            sb.AppendLine("Authors on PostsAuthors.AuthorId = Authors.AuthorId");
            sb.AppendLine("Where Authors.[Name] like '%' + @authorSearch + '%'");
            sb.AppendLine("END");

            migrationBuilder.Sql(sb.ToString());
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql("DROP PROCEDURE GetBlogForAuthorName");
        }
    }
}

次に、次のコードでそれを呼び出すことができます。

var blogs = _context.Blogs.FromSql("exec GetBlogForAuthorName @p0", "rod").Distinct();

後でいくつかの関連データ(投稿コンテンツなどの1対多の関係データ)を取得しようとしましたが、ブログは期待どおりに埋められた投稿コンテンツで戻ってきました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.