webentwicklung-frage-antwort-db.com.de

Unterstützt Entity Framework Code First gespeicherte Prozeduren?

Ich habe mehrere Präsentationen von EF Code First gesehen und nicht gesehen, wie EFCF mit gespeicherten Prozeduren funktioniert.

Wie kann ich eine Methode deklarieren, die sp verwendet? Kann ich eine Entität an eine Methode übergeben, die sp aufruft, ohne Entitätseigenschaften manuell sp-Parametern zuzuordnen?

Was passiert auch, wenn ich mein Modell ändere? Würde es meine SP fallen lassen, während ich den Tisch vom Modell wiederherstelle? Und was ist mit Auslösern?

Wenn diese Dinge nicht unterstützt werden, gibt es Pläne, sie in Zukunft zu unterstützen?

112
frennky

EDIT: Meine ursprüngliche Antwort für EF4.1 (unten) ist jetzt veraltet. Bitte sehen Sie die Antwort unten von Diego Vega (der im EF-Team bei Microsoft arbeitet)!


@gsharp und Shawn Mclean: Woher erhalten Sie diese Informationen? Haben Sie noch keinen Zugriff auf den zugrunde liegenden ObjectContext?

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

Ersetzen Sie die "select" -Anweisung durch einen gespeicherten proc, und los geht's.

Was deine andere Frage betrifft: Ja, leider werden deine s.p.'s verstopft. Möglicherweise müssen Sie die Anweisungen "CREATE PROCEDURE" in Ihren Code einfügen.

Für EF 4.2:

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

Update: Ab EF6 unterstützt EF Code First die Zuordnung gespeicherter Prozeduren für Einfügungen, Aktualisierungen und Löschvorgänge. Sie können die Zuordnung gespeicherter Prozeduren während der Modellerstellung mithilfe der MapToStoredProcedures-Methode angeben. Wir unterstützen auch das automatische Scaffolding grundlegender gespeicherter Prozeduren für diese Operationen. Siehe Funktionsbeschreibung hier .

Ursprüngliche Antwort: Die Zuordnung gespeicherter Prozeduren im Modell in Code-First in der ersten Version wird nicht unterstützt, und wir haben auch keine Möglichkeit dazu Erstellen Sie automatisch gespeicherte Prozeduren für CRUD-Operationen aus Ihren Typen. Dies sind Funktionen, die wir in Zukunft hinzufügen möchten.

Wie in diesem Thread erwähnt, kann auf ObjectContext zurückgegriffen werden, DbContext bietet jedoch auch nützliche APIs zum Ausführen nativer SQL-Abfragen und -Befehle (z. B. DbSet.SqlQuery, DbContext.Database.SqlQuery und DbContext.Database.ExecuteSqlCommand). Die verschiedenen SqlQuery-Versionen verfügen über die gleichen grundlegenden Materialisierungsfunktionen wie EF4 (wie ExecuteStoreQuery: http://msdn.Microsoft.com/en-us/library/dd487208.aspx ).

Hoffe das hilft.

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

Eine typsichere Lösung wäre:

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

Die Verwendung dieser Klasse ist:

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

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

Für .NET Core (EntityFrameworkCore) konnte ich sie zum Laufen bringen.

Könnte nicht die sauberste sein, aber das funktioniert definitiv.

Die Migration zum Hinzufügen der gespeicherten Prozedur sieht wie folgt aus :

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");
        }
    }
}

Ich könnte es dann mit dem folgenden Code aufrufen:

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

Später wurde versucht, einige der zugehörigen Daten abzurufen (eine bis mehrere Beziehungsdaten, z. B. Post-Inhalt), und der Blog wurde wie erwartet mit dem gefüllten Post-Inhalt zurückgegeben.

2
HockeyJ