Apakah Entity Framework Code First mendukung prosedur yang tersimpan?

112

Saya telah menyaksikan beberapa presentasi EF Code First dan belum melihat bagaimana EFCF bekerja dengan prosedur tersimpan.

Bagaimana saya bisa mendeklarasikan metode yang akan menggunakan beberapa sp? Dapatkah saya meneruskan entitas ke metode yang memanggil sp tanpa memetakan properti entitas secara manual ke parameter sp?

Selain itu, apa yang terjadi jika saya mengubah model saya? Apakah itu akan menjatuhkan sp saya saat membuat ulang tabel dari model? Dan bagaimana dengan pemicu?

Jika hal ini tidak didukung, apakah ada rencana untuk mendukungnya di masa mendatang?

frennky
sumber
5
Peta jalan EF menunjukkan bahwa EF 6 akan mendukung prosedur dan fungsi yang tersimpan untuk Kode Pertama. entityframework.codeplex.com/wikipage?title=Roadmap
frennky
Lihat juga: stackoverflow.com/questions/4873607/…
Nathan Koop

Jawaban:

66

EDIT: Jawaban asli saya untuk EF4.1 (di bawah) sekarang sudah usang. Silakan lihat jawaban di bawah ini dari Diego Vega (yang bekerja di tim EF di Microsoft)!


@gsharp dan Shawn Mclean: Dari mana Anda mendapatkan informasi ini? Apakah Anda masih memiliki akses ke ObjectContext yang mendasarinya?

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

Ganti pernyataan "pilih" dengan proc yang tersimpan, dan begitulah.

Adapun pertanyaan Anda yang lain: Ya, sayangnya sp Anda akan mati. Anda mungkin perlu menambahkan pernyataan "BUAT PROSEDUR" dalam kode Anda.

Untuk EF 4.2:

var customers = context.Database.SqlQuery<Customer>("select * from customers")
segera
sumber
Terima kasih. Bisakah Anda mengarahkan saya ke beberapa tautan yang memiliki info lebih lanjut tentang subjek ini.
frennky
1
Anda akan ingin mencari tiga fungsi Execute pada objek ObjectContext (ExecuteStoreQuery, ExecuteFunction, dan ExecuteStoreCommand).
segera
Saya salah paham dengan pertanyaan itu. Saya berpikir bahwa dia ingin membuat SP dan kode pertama.
gsharp
Anda dapat mengganti Context.OnModelCreating dan menambahkan logika khusus untuk membuat item database seperti procs yang disimpan melalui kode dengan cukup mudah. Tidak ideal tetapi dalam keadaan darurat itu akan berhasil.
Rick Strahl
Anda tidak memerlukan cast IObjectContextAdapter. DbContext dapat menangani pernyataan SQL sp atau kustom menggunakan objek Database bawaan: context.Database.SqlQuery <Dummy> ("sp_GetDummy");
Steven K.
50

Pembaruan: Dari EF6 dan seterusnya, EF Code First mendukung pemetaan prosedur tersimpan untuk penyisipan, pembaruan, dan penghapusan. Anda dapat menentukan pemetaan prosedur tersimpan selama pembuatan model menggunakan metode MapToStoredProcedures. Kami juga mendukung perancah otomatis dari prosedur tersimpan dasar untuk operasi tersebut. Lihat spesifikasi fiturnya di sini .

Jawaban asli: Kami tidak akan memiliki dukungan untuk memetakan prosedur yang tersimpan dalam model di Code-First pada rilis pertama, kami juga tidak akan memiliki cara untuk secara otomatis menghasilkan prosedur tersimpan untuk operasi CRUD dari tipe Anda. Ini adalah fitur yang ingin kami tambahkan di masa mendatang.

Seperti yang disebutkan di utas ini, dimungkinkan untuk kembali ke ObjectContext tetapi DbContext juga menyediakan API yang bagus untuk mengeksekusi kueri dan perintah SQL asli (mis. DbSet.SqlQuery, DbContext.Database.SqlQuery dan DbContext.Database.ExecuteSqlCommand). Versi SqlQuery yang berbeda memiliki fungsionalitas materialisasi dasar yang sama dengan yang ada di EF4 (seperti ExecuteStoreQuery: http://msdn.microsoft.com/en-us/library/dd487208.aspx ).

Semoga ini membantu.

divega
sumber
6
BTW, saya menulis posting blog beberapa hari yang lalu yang merinci bagaimana menggunakan metode ini untuk menjalankan prosedur yang tersimpan, bahkan prosedur tersimpan dengan parameter keluaran: blogs.msdn.com/b/diego/archive/2012/01/10/… .
divega
3
Akhir 2013, EF6 masih dalam pengembangan. Menunggu tiga tahun hanya untuk meningkatkan dukungan bagi tunas, mendesah.
DOK
1
@divega Apakah ada dukungan yang diketik dengan kuat untuk hanya memilih nilai dari prosedur tersimpan - pendekatan pertama kode ini tampaknya khusus untuk mengelola waktu hidup objek? Secara khusus, untuk penelusuran kompleks, menggunakan prosedur tersimpan spFooSearch dengan parameter keluaran TotalRows.
John Zabroski
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;
    }
Menandai
sumber
8

Solusi yang lebih aman jenisnya adalah ini:

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

Kegunaan kelas ini adalah:

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

var result = DbContext.Database.ExecuteStoredProcedure(testProcedureStoredProcedure);
Luc Bos
sumber
Tautan tidak lagi aktif, tetapi inilah arsipnya: web.archive.org/web/20150430090848/http://www.lucbos.net/2012/…
Arturo Torres Sánchez
2

Untuk .NET Core (EntityFrameworkCore), saya bisa membuatnya berfungsi.

Mungkin bukan yang paling rapi, tapi ini pasti berhasil.

Migrasi untuk menambahkan prosedur tersimpan terlihat seperti ini :

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

Saya kemudian dapat menyebutnya dengan kode berikut :

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

Kemudian mencoba mendapatkan beberapa data terkait (satu ke banyak data hubungan misalnya konten posting) dan blog kembali dengan isi posting seperti yang diharapkan.

HokiJ
sumber