Поддерживает ли Entity Framework Code First хранимые процедуры? - PullRequest
112 голосов
/ 30 января 2011

Я смотрел несколько презентаций EF Code First и не видел, как EFCF работает с хранимыми процедурами.

Как я могу объявить метод, который будет использовать некоторые sp? Могу ли я передать сущность методу, который вызывает sp, без сопоставления свойств сущности с параметрами sp вручную?

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

Если эти вещи не поддерживаются, планируется ли их поддержка в будущем?

Ответы [ 5 ]

66 голосов
/ 31 января 2011

РЕДАКТИРОВАТЬ: Мой первоначальный ответ для EF4.1 (ниже) устарел.Пожалуйста, смотрите ответ ниже от Диего Веги (который работает в команде EF в Microsoft)!


@ 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")
50 голосов
/ 31 января 2011

Обновление: Начиная с EF6, EF Code First поддерживает отображение хранимых процедур для вставок, обновлений и удалений. Вы можете указать отображение хранимой процедуры при создании модели, используя метод MapToStoredProcedures. Мы также поддерживаем автоматическое создание базовых хранимых процедур для этих операций. См. Спецификацию функции здесь .

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

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

Надеюсь, это поможет.

31 голосов
/ 21 сентября 2011
    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 голосов
/ 14 марта 2012

Более безопасное решение типа будет следующим:

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);
2 голосов
/ 28 октября 2016

Для .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");
        }
    }
}

Iзатем он может вызвать его с помощью следующего кода:

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...