Чи підтримує Entity Framework Code спочатку збережені процедури?


112

Я переглянув кілька презентацій коду EF спочатку і не побачив, як EFCF працює зі збереженими процедурами.

Як я можу оголосити метод, який використовує деякий sp? Чи можу я передати об'єкт методу, який викликає sp, не вручну відображаючи властивості сутності в параметри sp?

Також, що станеться, якщо я зміню свою модель? Буде це скинути мій sp під час відтворення таблиці з моделі? А як щодо тригерів?

Якщо ці речі не підтримуються, чи є плани на їх підтримку в майбутньому?


5
Дорожня карта EF вказує, що EF 6 підтримуватиме збережені процедури та функції для Code First. entitframework.codeplex.com/wikipage?title=Roadmap
frennky

Відповіді:


66

EDIT: Моя оригінальна відповідь для EF4.1 (нижче) застаріла. Дивіться відповідь нижче від Дієго Вега (який працює в команді EF в Microsoft)!


@gsharp та Shawn Mclean: Де ви отримуєте цю інформацію? Ви все ще не маєте доступу до основного ObjectContext?

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

Замініть оператор "select" на збережений прок, і ви переходите.

Що стосується вашого іншого питання: Так, на жаль, ваші спонсори отримають незлобленість. Можливо, вам доведеться додати у свій код заяви "СТВОРИТИ ПРОЦЕДУРУ".

Для EF 4.2:

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

Дякую. Чи можете ви вказати мені кілька посилань, які містять більше інформації про цю тему.
frennky

1
Вам потрібно буде знайти три функції Execute на об’єкті ObjectContext (ExecuteStoreQuery, ExecuteFunction і ExecuteStoreCommand).
анонс

Я неправильно зрозумів питання. Я думав, що він хоче спершу створити SP на основі коду.
gsharp

Ви можете замінити Context.OnModelCreating і додати користувацьку логіку для створення елементів бази даних, таких як збережені програми, за допомогою коду досить легко. Не ідеально, але в крайній мірі це зробить трюк.
Рік Страль

Вам не потрібен ролик IObjectContextAdapter. DbContext може обробляти висловлювання sp або користувальницькі SQL, використовуючи вбудований об'єкт бази даних: context.Database.SqlQuery <Dummy> ("sp_GetDummy");
Стівен К.

50

Оновлення: від EF6 і далі EF Code спочатку підтримує відображення збережених процедур для вставок, оновлень та видалень. Ви можете вказати збережене відображення процедур під час створення моделі за допомогою методу MapToStoredProcedures. Ми також підтримуємо автоматичні риштування основних базових процедур, що зберігаються для цих операцій. Дивіться специфікацію функції тут .

Оригінальна відповідь: Ми не матимемо підтримки для відображення збережених процедур у моделі в Code-First у першому випуску, а також у нас не буде способу автоматично генерувати збережені процедури для операцій CRUD з ваших типів. Це функції, які ми хотіли б додати в майбутньому.

Як було зазначено в цій темі, можна повернутися до ObjectContext, але DbContext також надає приємні API для виконання власних запитів і команд SQL (наприклад, DbSet.SqlQuery, DbContext.Database.SqlQuery і DbContext.Database.ExecuteSqC) Різні версії SqlQuery мають однаковий базовий функціонал матеріалізації, який існує в EF4 (як ExecuteStoreQuery: http://msdn.microsoft.com/en-us/library/dd487208.aspx ).

Сподіваюся, це допомагає.


6
До речі, я кілька днів тому написав повідомлення в блозі, де детально описано, як використовувати ці методи для виклику збережених процедур, навіть збережених процедур із вихідними параметрами: blogs.msdn.com/b/diego/archive/2012/01/10/… .
дівега

3
В кінці 2013 року EF6 ще в розробці. Чекаю три роки, щоб покращити підтримку паростків, зітхнути.
DOK

1
@divega Чи існує сильно набрана підтримка просто вибору значень із збереженої процедури - цей підхід, кодовий перший, видається специфічним для управління життєвим часом об'єкта? Зокрема, для складних пошуків із використанням збереженої процедури spFooSearch з вихідним параметром TotalRows.
Іван Заброський

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();

Пізніше спробували отримати деякі пов’язані дані (від одного до багатьох даних про стосунки, наприклад, вміст публікації), і щоденник повернувся із заповненим вмістом публікації, як вилучений.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.