Entity Framework Code First có hỗ trợ các thủ tục được lưu trữ không?


112

Tôi đã xem một số bản trình bày về EF Code First và chưa thấy EFCF hoạt động như thế nào với các thủ tục được lưu trữ.

Làm thế nào tôi có thể khai báo một phương thức sẽ sử dụng một số sp? Tôi có thể chuyển một thực thể tới một phương thức gọi sp mà không cần ánh xạ thủ công các thuộc tính của thực thể với các tham số sp không?

Ngoài ra, điều gì sẽ xảy ra nếu tôi thay đổi mô hình của mình? Nó có làm rơi sp của tôi trong khi tạo lại bảng từ mô hình không? Và những gì về kích hoạt?

Nếu những điều này không được hỗ trợ, có kế hoạch nào để hỗ trợ họ trong tương lai không?


5
Lộ trình của EF cho thấy EF 6 sẽ hỗ trợ các thủ tục và chức năng được lưu trữ cho Code First. entityframework.codeplex.com/wikipage?title=Roadmap
frennky

Câu trả lời:


66

CHỈNH SỬA: Câu trả lời ban đầu của tôi cho EF4.1 (bên dưới) hiện đã lỗi thời. Hãy xem câu trả lời dưới đây từ Diego Vega (người làm việc trong nhóm EF tại Microsoft)!


@gsharp và Shawn Mclean: Bạn lấy thông tin này ở đâu? Bạn vẫn có quyền truy cập vào ObjectContext bên dưới?

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

Thay thế câu lệnh "select" bằng một proc được lưu trữ, và bạn đã hoàn thành.

Đối với câu hỏi khác của bạn: Có, rất tiếc sp của bạn sẽ bị che phủ. Bạn có thể cần thêm câu lệnh "TẠO THỦ TỤC" trong mã của mình.

Đối với EF 4.2:

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

Cảm ơn. Bạn có thể chỉ cho tôi một số liên kết có thêm thông tin về chủ đề này.
điên cuồng

1
Bạn sẽ muốn tra cứu ba hàm Execute trên đối tượng ObjectContext (ExecuteStoreQuery, ExecuteFunction và ExecuteStoreCommand).
anon

Tôi đã hiểu sai câu hỏi. Tôi đã nghĩ rằng anh ấy muốn tạo ra mã của SP trước tiên.
gsharp

Bạn có thể ghi đè Context.OnModelCreating và thêm logic tùy chỉnh để tạo các mục cơ sở dữ liệu như procs được lưu trữ thông qua mã khá dễ dàng. Không lý tưởng nhưng trong một thời gian ngắn, nó sẽ làm được điều đó.
Rick Strahl

Bạn không cần truyền IObjectContextAdapter. DbContext có thể xử lý các câu lệnh SQL tùy chỉnh hoặc sp bằng cách sử dụng đối tượng Cơ sở dữ liệu tích hợp: context.Database.SqlQuery <Dummy> ("sp_GetDummy");
Steven K.

50

Cập nhật: Từ EF6 trở đi, EF Code First hỗ trợ ánh xạ thủ tục được lưu trữ để chèn, cập nhật và xóa. Bạn có thể chỉ định ánh xạ thủ tục được lưu trữ trong quá trình tạo mô hình bằng phương pháp MapToStoredProcedures. Chúng tôi cũng hỗ trợ giàn giáo tự động các quy trình lưu trữ cơ bản cho các hoạt động đó. Xem thông số kỹ thuật của tính năng tại đây .

Câu trả lời ban đầu: Chúng tôi sẽ không hỗ trợ ánh xạ các thủ tục được lưu trữ trong mô hình trong Code-First trong bản phát hành đầu tiên, cũng như chúng tôi sẽ không có cách tự động tạo các thủ tục được lưu trữ cho các hoạt động CRUD từ các loại của bạn. Đây là những tính năng mà chúng tôi muốn bổ sung trong tương lai.

Như nó đã được đề cập trong chủ đề này, có thể quay trở lại ObjectContext nhưng DbContext cũng cung cấp các API đẹp để thực thi các lệnh và truy vấn SQL gốc (ví dụ: DbSet.SqlQuery, DbContext.Database.SqlQuery và DbContext.Database.ExecuteSqlCommand). Các phiên bản SqlQuery khác nhau có cùng chức năng vật liệu hóa cơ bản tồn tại trong EF4 (như ExecuteStoreQuery: http://msdn.microsoft.com/en-us/library/dd487208.aspx ).

Hi vọng điêu nay co ich.


6
BTW, tôi đã viết một bài đăng trên blog cách đây vài ngày chi tiết cách sử dụng các phương thức này để gọi các thủ tục được lưu trữ, thậm chí cả các thủ tục được lưu trữ với các tham số đầu ra: blog.msdn.com/b/diego/archive/2012/01/10/… .
lặn biển

3
Cuối năm 2013, EF6 vẫn đang được phát triển. Chờ đợi ba năm chỉ để cải thiện hỗ trợ cho mầm, thở dài.
DOK

1
@divega Có hỗ trợ được đánh máy mạnh mẽ để chỉ chọn các giá trị từ một thủ tục được lưu trữ hay không - cách tiếp cận mã đầu tiên này có vẻ cụ thể để quản lý thời gian tồn tại của đối tượng? Cụ thể, đối với các tìm kiếm phức tạp, sử dụng thủ tục lưu trữ spFooSearch với tham số đầu ra 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;
    }

8

Một giải pháp an toàn hơn sẽ là:

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

Cách sử dụng của lớp này là:

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

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

Liên kết không còn hoạt động nữa nhưng đây là kho lưu trữ: web.archive.org/web/20150430090848/http://www.lucbos.net/2012/…
Arturo Torres Sánchez

2

Đối với .NET Core (EntityFrameworkCore), tôi đã có thể làm cho chúng hoạt động.

Có thể không phải là gọn gàng nhất, nhưng điều này chắc chắn hiệu quả.

Quá trình di chuyển để thêm thủ tục được lưu trữ trông giống như sau :

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

Sau đó tôi có thể gọi nó bằng mã sau :

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

Sau đó, đã thử lấy một số dữ liệu liên quan (một đến nhiều dữ liệu mối quan hệ, ví dụ như nội dung Bài đăng) và blog đã quay trở lại với nội dung Bài đăng đã điền như đã bị xóa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.