Код Entity Framework Сначала поддерживаются хранимые процедуры?
Я просмотрел несколько презентаций EF Code First и не видел, как EFCF работает с хранимыми процедурами.
Как я могу объявить метод, который будет использовать некоторый sp? Могу ли я передать объект методу, который вызывает sp без ручной привязки свойств объекта к параметрам sp?
Кроме того, что произойдет, если я изменю свою модель? Будет ли это падение моей sp при воссоздании таблицы из модели? А как насчет триггеров?
Если эти вещи не поддерживаются, есть ли планы поддержать их в будущем?
Ответы
Ответ 1
EDIT: Мой оригинальный ответ для EF4.1 (ниже) теперь устарел. Пожалуйста, см. ответ ниже от Diego Vega (который работает в команде EF в Microsoft)!
@gsharp и Shawn Mclean: Где вы получаете эту информацию? У вас еще нет доступа к базовому объектно-ориентированному объекту?
IEnumerable<Customer> customers =
((IObjectContextAdapter)this)
.ObjectContext.ExecuteStoreQuery<Customer>("select * from customers");
Замените оператор "select" сохраненным proc, и там вы идете.
Что касается вашего другого вопроса: Да, к сожалению, ваш s.p. будут сбиты. Вам может потребоваться добавить в свой код инструкции "CREATE PROCEDURE".
Для EF 4.2:
var customers = context.Database.SqlQuery<Customer>("select * from customers")
Ответ 2
Обновление: От EF6 on, 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).
Надеюсь, что это поможет.
Ответ 3
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;
}
Ответ 4
Более безопасным решением типа будет следующее:
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);
Ответ 5
Для .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");
}
}
}
Затем я мог бы вызвать его с помощью следующего кода:
var blogs = _context.Blogs.FromSql("exec GetBlogForAuthorName @p0", "rod").Distinct();
Позже попытался получить некоторые из связанных данных (от одного до многих данных о взаимоотношениях, например, от сообщений), и блог вернулся с заполненным сообщением Post как exptected.