2011-01-30 24 views
111

Ho visto diverse presentazioni di EF Code First e non ho visto come EFCF funzioni con stored procedure.Il codice di Entity Framework supporta prima le stored procedure?

Come posso dichiarare un metodo che utilizzerà un po 'di sp? Posso passare un'entità a un metodo che chiama sp senza mappare manualmente le proprietà dell'entità ai parametri sp?

Inoltre, cosa succede se cambio la mia modella? Vuoi lasciare il mio sp mentre ricrea il tavolo dal modello? E i trigger?

Se queste cose non sono supportate, ci sono piani per supportarle in futuro?

+5

La tabella di marcia EF indica che EF 6 supporterà procedure e funzioni memorizzate per Code First. http://entityframework.codeplex.com/wikipage?title=Roadmap – frennky

+0

Vedi anche: http://stackoverflow.com/questions/4873607/how-to-use-dbcontext-database-sqlquerytelementsql-params-with-stored-proced –

risposta

66

MODIFICA: La mia risposta originale per EF4.1 (sotto) non è più aggiornata. Si prega di vedere the answer below from Diego Vega (chi lavora nel team EF di Microsoft)!


@gsharp e Shawn Mclean: Dove vengono visualizzate queste informazioni? Non hai ancora accesso all'oggetto ObjectContext sottostante?

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

Sostituire l'istruzione "select" con un proc memorizzato ed ecco fatto.

Come per la tua altra domanda: Sì, sfortunatamente le tue risposte verranno sbalordite. Potrebbe essere necessario aggiungere le istruzioni "CREATE PROCEDURE" nel codice.

Per EF 4.2:

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

Grazie. Potresti indicarmi alcuni collegamenti che hanno maggiori informazioni su questo argomento. – frennky

+1

Si desidera cercare le tre funzioni Execute sull'oggetto ObjectContext (ExecuteStoreQuery, ExecuteFunction ed ExecuteStoreCommand). – anon

+0

Ho frainteso la domanda. Stavo pensando che vuole creare la prima base di SP e un codice. – gsharp

50

Aggiornamento: Da EF6 su, EF Codice Prima supporta immagazzinata mappatura procedura per inserimenti, aggiornamenti ed eliminazioni. È possibile specificare il mapping della stored procedure durante la creazione del modello mediante il metodo MapToStoredProcedures. Supportiamo anche l'impalcatura automatica delle procedure di archiviazione di base per tali operazioni. Vedere le specifiche della funzione here.

risposta originale: Noi non avrà il supporto per le stored procedure di mappatura del modello Codice-Primo nella prima versione, né noi avrà un modo per generare automaticamente le stored procedure per le operazioni CRUD dai vostri tipi. Queste sono funzionalità che vorremmo aggiungere in futuro.

Come è stato detto in questo thread, è possibile ripiegare a ObjectContext ma DbContext fornisce anche API piacevoli per eseguire query SQL nativi e comandi (ad esempio DbSet.SqlQuery, DbContext.Database.SqlQuery e DbContext.Database.ExecuteSqlCommand). Le diverse versioni di SqlQuery hanno la stessa funzionalità di materializzazione di base che esiste in EF4 (come ExecuteStoreQuery: http://msdn.microsoft.com/en-us/library/dd487208.aspx).

Spero che questo aiuti.

+6

BTW, ho scritto un post sul blog alcuni giorni fa che spiega come utilizzare questi metodi per richiamare stored procedure, anche stored procedure con parametri di output: http://blogs.msdn.com/b/diego/archive/2012/01 /10/how-to-execute-stored-procedures-sqlquery-in-the-dbcontext-api.aspx. – divega

+3

Fine 2013, EF6 è ancora in sviluppo. Aspettando tre anni solo per migliorare il supporto per sprocs, sospiro. – DOK

+1

@divega Esiste un supporto fortemente tipizzato per la semplice selezione di valori da una stored procedure: questo approccio code-first sembra specifico per la gestione della vita dell'oggetto? In particolare, per ricerche complesse, utilizzando una stored procedure spFooSearch con un parametro di output 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

Una soluzione sicura più tipo sarebbe questo:

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

L'utilizzo di questa classe è:

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

var result = DbContext.Database.ExecuteStoredProcedure(testProcedureStoredProcedure); 
+0

Il link non è più attivo, ma ecco l'archivio: http://web.archive.org/web/20150430090848/http://www.lucbos.net/2012/03/calling-stored-procedure-with-entity .html –

2

Per .NET core (EntityFrameworkCore), sono stato in grado di farli funzionare.

Potrebbe non essere il più accurato, ma funziona sicuramente.

La migrazione per aggiungere la stored procedure assomiglia 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"); 
     } 
    } 
} 

ho potuto quindi chiamare con il codice following:

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

tardi tentato di ottenere alcuni dei dati relativi (uno a molti dati relazionali, ad esempio Pubblica contenuti) e il blog è tornato con il contenuto del post riempito come è stato verificato.

Problemi correlati