web-dev-qa-db-ja.com

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

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

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

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

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

112
frennky

EDIT:EF4.1(以下)に対する私の元の答えは現在古くなっています。 Diego Vegaからの以下の回答 (MicrosoftのEFチームで働いている)をご覧ください!


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

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

「select」ステートメントをストアドプロシージャに置き換えれば、そこに行きます。

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

EF 4.2の場合:

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

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

元の答え:最初のリリースではCode-Firstのモデルのストアドプロシージャのマッピングはサポートされていません。型からCRUD操作のストアドプロシージャを自動的に生成します。これらは、将来追加したい機能です。

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

お役に立てれば。

50
divega
    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;
    }
31
Mark

より安全なタイプのソリューションは次のとおりです。

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);
8
Luc Bos

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

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

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

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

それから following コードで呼び出すことができます:

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

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

2
HockeyJ