web-dev-qa-db-fra.com

Entity Framework Code First prend-il en charge les procédures stockées?

J'ai regardé plusieurs présentations de EF Code First et je n'ai pas vu comment EFCF fonctionne avec les procédures stockées.

Comment puis-je déclarer une méthode qui utilisera certains sp? Puis-je transmettre une entité à une méthode qui appelle sp sans mapper manuellement les propriétés d'entité avec les paramètres sp?

Aussi, que se passe-t-il si je change de modèle? Est-ce que cela laisserait tomber mon sp lorsque je recréerais une table à partir d'un modèle? Et qu'en est-il des déclencheurs?

Si ces éléments ne sont pas pris en charge, existe-t-il des projets pour les prendre en charge à l'avenir?

112
frennky

EDIT: Ma réponse d'origine pour EF4.1 (ci-dessous) est maintenant obsolète. S'il vous plaît voir la réponse ci-dessous de Diego Vega (qui travaille sur l'équipe EF de Microsoft)!


@gsharp et Shawn Mclean: Où obtenez-vous cette information? N'avez-vous toujours pas accès au ObjectContext sous-jacent?

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

Remplacez l'instruction "select" par un proc stocké, et voilà.

Pour ce qui est de votre autre question: oui, malheureusement, vos collègues vont se faire avoir. Vous devrez peut-être ajouter les instructions "CREATE PROCEDURE" dans votre code.

Pour EF 4.2:

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

Mise à jour: À partir de EF6, EF Code First prend en charge le mappage de procédures stockées pour les insertions, les mises à jour et les suppressions. Vous pouvez spécifier un mappage de procédure stockée lors de la création d'un modèle à l'aide de la méthode MapToStoredProcedures. Nous soutenons également l'échafaudage automatique des procédures stockées de base pour ces opérations. Voir la spécification de la fonctionnalité ici .

Réponse originale: Nous ne prendrons pas en charge la mise en correspondance des procédures stockées dans le modèle dans Code-First dans la première version, ni un moyen de générer automatiquement des procédures stockées pour les opérations CRUD à partir de vos types. Ce sont des fonctionnalités que nous aimerions ajouter à l'avenir.

Comme il a été mentionné dans ce fil de discussion, il est possible de revenir à ObjectContext, mais DbContext fournit également des API Nice permettant d'exécuter des requêtes et des commandes SQL natives (par exemple, DbSet.SqlQuery, DbContext.Database.SqlQuery et DbContext.Database.ExecuteSqlCommand). Les différentes versions de SqlQuery ont la même fonctionnalité de matérialisation de base que celle disponible dans EF4 (comme ExecuteStoreQuery: http://msdn.Microsoft.com/en-us/library/dd487208.aspx ).

J'espère que cela t'aides.

50
divega
    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;
    }
31
Mark

Voici une solution plus sûre:

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

L'utilisation de cette classe est:

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

var result = DbContext.Database.ExecuteStoredProcedure(testProcedureStoredProcedure);
8
Luc Bos

Pour .NET Core (EntityFrameworkCore), j'ai pu les faire fonctionner.

Ce n'est peut-être pas le meilleur, mais cela fonctionne vraiment.

La migration pour l'ajout de la procédure stockée ressemble à 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");
        }
    }
}

Je pourrais alors l'appeler avec le code suivant :

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

Plus tard, nous avons essayé d’obtenir certaines des données associées (une à plusieurs données sur les relations, par exemple, le contenu du post) et le blog est revenu avec le contenu du post rempli comme prévu.

2
HockeyJ