c# - sqlquery - mapear stored procedure entity framework
¿El primer código del Entity Framework Code es compatible con los procedimientos almacenados? (5)
Para .NET Core (EntityFrameworkCore), he podido hacer que funcionen.
Puede que no sea el mejor, pero esto definitivamente funciona.
La migración para agregar el procedimiento almacenado se ve así:
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");
}
}
}
Podría llamarlo con el following código:
var blogs = _context.Blogs.FromSql("exec GetBlogForAuthorName @p0", "rod").Distinct();
Más tarde intenté obtener algunos de los datos relacionados (de uno a muchos datos de relación, por ejemplo, contenido de publicación) y el blog volvió con el contenido del mensaje completo como se expiró.
He visto varias presentaciones de EF Code First y no he visto cómo funciona EFCF con los procedimientos almacenados.
¿Cómo puedo declarar un método que utilizará algunos sp? ¿Puedo pasar una entidad a un método que llame a sp sin mapear manualmente las propiedades de la entidad a los parámetros sp?
Además, ¿qué sucede si cambio mi modelo? ¿Dejaría caer mi sp mientras recreaba la mesa del modelo? ¿Y qué hay de los disparadores?
Si estas cosas no son compatibles, ¿hay algún plan para apoyarlas en el futuro?
Una solución segura más tipo sería esta:
http://strugglesofacoder.blogspot.be/2012/03/calling-stored-procedure-with-entity.html
El uso de esta clase es:
var testProcedureStoredProcedure = new TestProcedureStoredProcedure() { Iets = 5, NogIets = true };
var result = DbContext.Database.ExecuteStoredProcedure(testProcedureStoredProcedure);
Actualización: desde EF6 activado, EF Code First admite la asignación de procedimientos almacenados para inserciones, actualizaciones y eliminaciones. Puede especificar la asignación de procedimientos almacenados durante la creación del modelo utilizando el método MapToStoredProcedures. También admitimos el andamiaje automático de procedimientos almacenados básicos para esas operaciones. Vea la especificación de la función here .
Respuesta original: no tendremos soporte para mapear procedimientos almacenados en el modelo en Code-First en la primera versión, ni tendremos una manera de generar automáticamente procedimientos almacenados para operaciones CRUD de sus tipos. Estas son características que nos gustaría agregar en el futuro.
Como se mencionó en este hilo, es posible recurrir a ObjectContext, pero DbContext también proporciona agradables API para ejecutar consultas y comandos SQL nativos (por ejemplo, DbSet.SqlQuery, DbContext.Database.SqlQuery y DbContext.Database.ExecuteSqlCommand). Las diferentes versiones de SqlQuery tienen la misma funcionalidad de materialización básica que existe en EF4 (como ExecuteStoreQuery: http://msdn.microsoft.com/en-us/library/dd487208.aspx ).
Espero que esto ayude.
EDITAR: Mi respuesta original para EF4.1 (abajo) ahora está desactualizada. Por favor, vea la respuesta a continuación de Diego Vega (¡que trabaja en el equipo de EF en Microsoft)!
@gsharp y Shawn Mclean: ¿De dónde sacas esta información? ¿Todavía no tienes acceso al ObjectContext subyacente?
IEnumerable<Customer> customers =
((IObjectContextAdapter)this)
.ObjectContext.ExecuteStoreQuery<Customer>("select * from customers");
Reemplaza la instrucción "seleccionar" con un proceso almacenado, y listo.
En cuanto a tu otra pregunta: Sí, desafortunadamente tus sp''s serán golpeados. Es posible que deba agregar las instrucciones "CREAR PROCEDIMIENTO" en su código.
Para EF 4.2:
var customers = context.Database.SqlQuery<Customer>("select * from customers")
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;
}