Code First gespeicherte Prozeduren INSERT, Update und DELETECode First Insert, Update, and Delete Stored Procedures

Hinweis

Nur EF6 und höher: Die Features, APIs usw., die auf dieser Seite erläutert werden, wurden in Entity Framework 6 eingeführt.EF6 Onwards Only - The features, APIs, etc. discussed in this page were introduced in Entity Framework 6. Wenn Sie eine frühere Version verwenden, gelten manche Informationen nicht.If you are using an earlier version, some or all of the information does not apply.

Standardmäßig konfiguriert Code First alle Entitäten so, dass INSERT-, Update-und DELETE-Befehle mithilfe des direkten Tabellen Zugriffs durchgeführt werden.By default, Code First will configure all entities to perform insert, update and delete commands using direct table access. Beginnend mit EF6 können Sie das Code First Modell so konfigurieren, dass es gespeicherte Prozeduren für einige oder alle Entitäten im Modell verwendet.Starting in EF6 you can configure your Code First model to use stored procedures for some or all entities in your model.

Grundlegende Entitäts ZuordnungBasic Entity Mapping

Sie können gespeicherte Prozeduren für INSERT, Update und DELETE mithilfe der fließend-API verwenden.You can opt into using stored procedures for insert, update and delete using the Fluent API.

modelBuilder
  .Entity<Blog>()
  .MapToStoredProcedures();

Dies führt dazu, dass Code First einige Konventionen verwenden, um die erwartete Form der gespeicherten Prozeduren in der Datenbank zu erstellen.Doing this will cause Code First to use some conventions to build the expected shape of the stored procedures in the database.

  • Drei gespeicherte Prozeduren namens ** <type_name> _INSERT**, ** <type_name> _Update** und ** <type_name> _Delete** (z. b. Blog_Insert, Blog_Update und Blog_Delete).Three stored procedures named <type_name>_Insert, <type_name>_Update and <type_name>_Delete (for example, Blog_Insert, Blog_Update and Blog_Delete).
  • Parameter Namen entsprechen den Eigenschaftsnamen.Parameter names correspond to the property names.

    Hinweis

    Wenn Sie hascolumnname () oder das Column-Attribut verwenden, um die Spalte für eine bestimmte Eigenschaft umzubenennen, wird dieser Name für Parameter anstelle des Eigenschafts namens verwendet.If you use HasColumnName() or the Column attribute to rename the column for a given property then this name is used for parameters instead of the property name.

  • Die gespeicherte Prozedur INSERT verfügt über einen Parameter für jede Eigenschaft, mit Ausnahme derjenigen, die als vom Store generiert (Identität oder berechnet) gekennzeichnet sind.The insert stored procedure will have a parameter for every property, except for those marked as store generated (identity or computed). Die gespeicherte Prozedur sollte ein Resultset mit einer Spalte für jede vom Speicher generierte Eigenschaft zurückgeben.The stored procedure should return a result set with a column for each store generated property.
  • Die gespeicherte Update Prozedur verfügt über einen Parameter für jede Eigenschaft, mit Ausnahme derjenigen, die mit einem vom Speicher generierten Muster "berechnet" gekennzeichnet sind.The update stored procedure will have a parameter for every property, except for those marked with a store generated pattern of 'Computed'. Einige Parallelitäts Token erfordern einen Parameter für den ursprünglichen Wert. Weitere Informationen finden Sie im Abschnitt Parallelitäts Token weiter unten.Some concurrency tokens require a parameter for the original value, see the Concurrency Tokens section below for details. Die gespeicherte Prozedur sollte ein Resultset mit einer Spalte für jede berechnete Eigenschaft zurückgeben.The stored procedure should return a result set with a column for each computed property.
  • Die gespeicherte DELETE-Prozedur muss über einen Parameter für den Schlüsselwert der Entität verfügen (oder mehrere Parameter, wenn die Entität über einen zusammengesetzten Schlüssel verfügt).The delete stored procedure should have a parameter for the key value of the entity (or multiple parameters if the entity has a composite key). Außerdem sollte die Delete-Prozedur auch über Parameter für alle unabhängigen Zuordnungs Fremdschlüssel in der Ziel Tabelle verfügen (Beziehungen, die keine entsprechenden Fremdschlüssel Eigenschaften haben, die in der Entität deklariert sind).Additionally, the delete procedure should also have parameters for any independent association foreign keys on the target table (relationships that do not have corresponding foreign key properties declared in the entity). Einige Parallelitäts Token erfordern einen Parameter für den ursprünglichen Wert. Weitere Informationen finden Sie im Abschnitt Parallelitäts Token weiter unten.Some concurrency tokens require a parameter for the original value, see the Concurrency Tokens section below for details.

Verwenden Sie die folgende Klasse als Beispiel:Using the following class as an example:

public class Blog  
{  
  public int BlogId { get; set; }  
  public string Name { get; set; }  
  public string Url { get; set; }  
}

Die gespeicherten Standard Prozeduren lauten wie folgt:The default stored procedures would be:

CREATE PROCEDURE [dbo].[Blog_Insert]  
  @Name nvarchar(max),  
  @Url nvarchar(max)  
AS  
BEGIN
  INSERT INTO [dbo].[Blogs] ([Name], [Url])
  VALUES (@Name, @Url)

  SELECT SCOPE_IDENTITY() AS BlogId
END
CREATE PROCEDURE [dbo].[Blog_Update]  
  @BlogId int,  
  @Name nvarchar(max),  
  @Url nvarchar(max)  
AS  
  UPDATE [dbo].[Blogs]
  SET [Name] = @Name, [Url] = @Url     
  WHERE BlogId = @BlogId;
CREATE PROCEDURE [dbo].[Blog_Delete]  
  @BlogId int  
AS  
  DELETE FROM [dbo].[Blogs]
  WHERE BlogId = @BlogId

Überschreiben der StandardwerteOverriding the Defaults

Sie können einen Teil oder alle der standardmäßig konfigurierten Einstellungen außer Kraft setzen.You can override part or all of what was configured by default.

Sie können den Namen einer oder mehrerer gespeicherter Prozeduren ändern.You can change the name of one or more stored procedures. In diesem Beispiel wird nur die gespeicherte Update Prozedur umbenannt.This example renames the update stored procedure only.

modelBuilder  
  .Entity<Blog>()  
  .MapToStoredProcedures(s =>  
    s.Update(u => u.HasName("modify_blog")));

In diesem Beispiel werden alle drei gespeicherten Prozeduren umbenannt.This example renames all three stored procedures.

modelBuilder  
  .Entity<Blog>()  
  .MapToStoredProcedures(s =>  
    s.Update(u => u.HasName("modify_blog"))  
     .Delete(d => d.HasName("delete_blog"))  
     .Insert(i => i.HasName("insert_blog")));

In diesen Beispielen werden die Aufrufe miteinander verkettet, aber Sie können auch die Lambda-Block Syntax verwenden.In these examples the calls are chained together, but you can also use lambda block syntax.

modelBuilder  
  .Entity<Blog>()  
  .MapToStoredProcedures(s =>  
    {  
      s.Update(u => u.HasName("modify_blog"));  
      s.Delete(d => d.HasName("delete_blog"));  
      s.Insert(i => i.HasName("insert_blog"));  
    });

In diesem Beispiel wird der-Parameter für die BlogId-Eigenschaft der gespeicherten Update-Prozedur umbenannt.This example renames the parameter for the BlogId property on the update stored procedure.

modelBuilder  
  .Entity<Blog>()  
  .MapToStoredProcedures(s =>  
    s.Update(u => u.Parameter(b => b.BlogId, "blog_id")));

Diese Aufrufe sind alle verkettbar und zusammensetzbar.These calls are all chainable and composable. Es folgt ein Beispiel, das alle drei gespeicherten Prozeduren und ihre Parameter umbenennt.Here is an example that renames all three stored procedures and their parameters.

modelBuilder  
  .Entity<Blog>()  
  .MapToStoredProcedures(s =>  
    s.Update(u => u.HasName("modify_blog")  
                   .Parameter(b => b.BlogId, "blog_id")  
                   .Parameter(b => b.Name, "blog_name")  
                   .Parameter(b => b.Url, "blog_url"))  
     .Delete(d => d.HasName("delete_blog")  
                   .Parameter(b => b.BlogId, "blog_id"))  
     .Insert(i => i.HasName("insert_blog")  
                   .Parameter(b => b.Name, "blog_name")  
                   .Parameter(b => b.Url, "blog_url")));

Sie können auch den Namen der Spalten im Resultset ändern, das von der Datenbank generierte Werte enthält.You can also change the name of the columns in the result set that contains database generated values.

modelBuilder
  .Entity<Blog>()
  .MapToStoredProcedures(s =>
    s.Insert(i => i.Result(b => b.BlogId, "generated_blog_identity")));
CREATE PROCEDURE [dbo].[Blog_Insert]  
  @Name nvarchar(max),  
  @Url nvarchar(max)  
AS  
BEGIN
  INSERT INTO [dbo].[Blogs] ([Name], [Url])
  VALUES (@Name, @Url)

  SELECT SCOPE_IDENTITY() AS generated_blog_id
END

Beziehungen ohne Fremdschlüssel in der Klasse (unabhängige Zuordnungen)Relationships Without a Foreign Key in the Class (Independent Associations)

Wenn eine Fremdschlüssel Eigenschaft in der Klassendefinition enthalten ist, kann der entsprechende Parameter auf dieselbe Weise wie jede andere Eigenschaft umbenannt werden.When a foreign key property is included in the class definition, the corresponding parameter can be renamed in the same way as any other property. Wenn eine Beziehung ohne Fremdschlüssel Eigenschaft in der-Klasse vorhanden ist, lautet der Standardparameter Name ** <navigation_property_name> _ <primary_key_name> **.When a relationship exists without a foreign key property in the class, the default parameter name is <navigation_property_name>_<primary_key_name>.

Beispielsweise würden die folgenden Klassendefinitionen dazu führen, dass in den gespeicherten Prozeduren ein Blog_BlogId-Parameter erwartet wird, um Beiträge einzufügen und zu aktualisieren.For example, the following class definitions would result in a Blog_BlogId parameter being expected in the stored procedures to insert and update Posts.

public class Blog  
{  
  public int BlogId { get; set; }  
  public string Name { get; set; }  
  public string Url { get; set; }

  public List<Post> Posts { get; set; }  
}  

public class Post  
{  
  public int PostId { get; set; }  
  public string Title { get; set; }  
  public string Content { get; set; }  

  public Blog Blog { get; set; }  
}

Überschreiben der StandardwerteOverriding the Defaults

Sie können Parameter für Fremdschlüssel, die nicht in der-Klasse enthalten sind, ändern, indem Sie der-Parameter Methode den Pfad zur Primary Key-Eigenschaft bereitstellen.You can change parameters for foreign keys that are not included in the class by supplying the path to the primary key property to the Parameter method.

modelBuilder
  .Entity<Post>()  
  .MapToStoredProcedures(s =>  
    s.Insert(i => i.Parameter(p => p.Blog.BlogId, "blog_id")));

Wenn Sie nicht über eine Navigations Eigenschaft für die abhängige Entität verfügen (d. h.If you don’t have a navigation property on the dependent entity (i.e No Post. Blog-Eigenschaft) Anschließend können Sie die Association-Methode verwenden, um das andere Ende der Beziehung zu identifizieren und dann die Parameter zu konfigurieren, die den einzelnen Schlüsseleigenschaften entsprechen.no Post.Blog property) then you can use the Association method to identify the other end of the relationship and then configure the parameters that correspond to each of the key property(s).

modelBuilder
  .Entity<Post>()  
  .MapToStoredProcedures(s =>  
    s.Insert(i => i.Navigation<Blog>(  
      b => b.Posts,  
      c => c.Parameter(b => b.BlogId, "blog_id"))));

ParallelitätstokenConcurrency Tokens

Die gespeicherten Prozeduren Update und DELETE müssen möglicherweise auch die Parallelität behandeln:Update and delete stored procedures may also need to deal with concurrency:

  • Wenn die Entität Parallelitäts Token enthält, kann die gespeicherte Prozedur optional über einen Output-Parameter verfügen, der die Anzahl der aktualisierten/gelöschten Zeilen (betroffene Zeilen) zurückgibt.If the entity contains concurrency tokens, the stored procedure can optionally have an output parameter that returns the number of rows updated/deleted (rows affected). Ein solcher Parameter muss mithilfe der rowsaffectedparameter-Methode konfiguriert werden.Such a parameter must be configured using the RowsAffectedParameter method.
    Standardmäßig verwendet EF den Rückgabewert von ExecuteNonQuery, um zu bestimmen, wie viele Zeilen betroffen sind.By default EF uses the return value from ExecuteNonQuery to determine how many rows were affected. Das Angeben eines betroffenen Rows-Ausgabe Parameters ist nützlich, wenn Sie eine Logik in Ihrem SPROC ausführen, die dazu führt, dass der Rückgabewert von ExecuteNonQuery beim Ende der Ausführung falsch ist (aus EF-Sicht).Specifying a rows affected output parameter is useful if you perform any logic in your sproc that would result in the return value of ExecuteNonQuery being incorrect (from EF's perspective) at the end of execution.
  • Für jedes Parallelitäts Token gibt es einen Parameter mit dem Namen ** <property_name> _Original** (z. b. Timestamp_Original).For each concurrency token there will be a parameter named <property_name>_Original (for example, Timestamp_Original ). Diesem wird der ursprüngliche Wert dieser Eigenschaft – der Wert, wenn er aus der Datenbank abgefragt wird.This will be passed the original value of this property – the value when queried from the database.
    • Parallelitäts Token, die von der Datenbank berechnet werden – z. b. Zeitstempel – verfügen nur über einen ursprünglichen value-Parameter.Concurrency tokens that are computed by the database – such as timestamps – will only have an original value parameter.
    • Nicht berechnete Eigenschaften, die als Parallelitäts Token festgelegt werden, verfügen ebenfalls über einen Parameter für den neuen Wert in der Aktualisierungs Prozedur.Non-computed properties that are set as concurrency tokens will also have a parameter for the new value in the update procedure. Dabei werden die Benennungs Konventionen verwendet, die bereits für neue Werte erläutert wurden.This uses the naming conventions already discussed for new values. Ein Beispiel für ein solches Token wäre die Verwendung einer Blog-URL als Parallelitäts Token. der neue Wert ist erforderlich, da dies durch Ihren Code auf einen neuen Wert aktualisiert werden kann (im Gegensatz zu einem Timestamp-Token, das nur von der Datenbank aktualisiert wird).An example of such a token would be using a Blog's URL as a concurrency token, the new value is required because this can be updated to a new value by your code (unlike a Timestamp token which is only updated by the database).

Dies ist eine Beispiel Klasse und eine gespeicherte Aktualisierungs Prozedur mit einem Zeitstempel-Parallelitäts Token.This is an example class and update stored procedure with a timestamp concurrency token.

public class Blog  
{  
  public int BlogId { get; set; }  
  public string Name { get; set; }  
  public string Url { get; set; }  
  [Timestamp]
  public byte[] Timestamp { get; set; }
}
CREATE PROCEDURE [dbo].[Blog_Update]  
  @BlogId int,  
  @Name nvarchar(max),  
  @Url nvarchar(max),
  @Timestamp_Original rowversion  
AS  
  UPDATE [dbo].[Blogs]
  SET [Name] = @Name, [Url] = @Url     
  WHERE BlogId = @BlogId AND [Timestamp] = @Timestamp_Original

Im folgenden finden Sie eine Beispiel Klasse und eine gespeicherte Aktualisierungs Prozedur mit einem nicht berechneten Parallelitäts Token.Here is an example class and update stored procedure with non-computed concurrency token.

public class Blog  
{  
  public int BlogId { get; set; }  
  public string Name { get; set; }  
  [ConcurrencyCheck]
  public string Url { get; set; }  
}
CREATE PROCEDURE [dbo].[Blog_Update]  
  @BlogId int,  
  @Name nvarchar(max),  
  @Url nvarchar(max),
  @Url_Original nvarchar(max),
AS  
  UPDATE [dbo].[Blogs]
  SET [Name] = @Name, [Url] = @Url     
  WHERE BlogId = @BlogId AND [Url] = @Url_Original

Überschreiben der StandardwerteOverriding the Defaults

Optional können Sie den Parameter "betroffene Zeilen" einführen.You can optionally introduce a rows affected parameter.

modelBuilder  
  .Entity<Blog>()  
  .MapToStoredProcedures(s =>  
    s.Update(u => u.RowsAffectedParameter("rows_affected")));

Für berechnete Parallelitäts Token für die Datenbank – Wenn nur der ursprüngliche Wert übergeben wird – können Sie einfach den Standardparameter Umbenennungs Mechanismus verwenden, um den Parameter für den ursprünglichen Wert umzubenennen.For database computed concurrency tokens – where only the original value is passed – you can just use the standard parameter renaming mechanism to rename the parameter for the original value.

modelBuilder  
  .Entity<Blog>()  
  .MapToStoredProcedures(s =>  
    s.Update(u => u.Parameter(b => b.Timestamp, "blog_timestamp")));

Bei nicht berechneten Parallelitäts Token – wobei sowohl der ursprüngliche als auch der neue Wert übergeben werden – können Sie eine Überladung des Parameters verwenden, mit der Sie für jeden Parameter einen Namen angeben können.For non-computed concurrency tokens – where both the original and new value are passed – you can use an overload of Parameter that allows you to supply a name for each parameter.

modelBuilder
 .Entity<Blog>()
 .MapToStoredProcedures(s => s.Update(u => u.Parameter(b => b.Url, "blog_url", "blog_original_url")));

m:n-BeziehungenMany to Many Relationships

Wir verwenden die folgenden Klassen als Beispiel in diesem Abschnitt.We’ll use the following classes as an example in this section.

public class Post  
{  
  public int PostId { get; set; }  
  public string Title { get; set; }  
  public string Content { get; set; }  

  public List<Tag> Tags { get; set; }  
}  

public class Tag  
{  
  public int TagId { get; set; }  
  public string TagName { get; set; }  

  public List<Post> Posts { get; set; }  
}

Viele zu viele Beziehungen können gespeicherten Prozeduren mit der folgenden Syntax zugeordnet werden.Many to many relationships can be mapped to stored procedures with the following syntax.

modelBuilder  
  .Entity<Post>()  
  .HasMany(p => p.Tags)  
  .WithMany(t => t.Posts)  
  .MapToStoredProcedures();

Wenn keine andere Konfiguration bereitgestellt wird, wird standardmäßig die folgende Form der gespeicherten Prozedur verwendet.If no other configuration is supplied then the following stored procedure shape is used by default.

  • Zwei gespeicherte Prozeduren namens ** <type_one> <type_two> _INSERT** und ** <type_one> <type_two> _Delete** (z. b. PostTag_Insert und PostTag_Delete).Two stored procedures named <type_one><type_two>_Insert and <type_one><type_two>_Delete (for example, PostTag_Insert and PostTag_Delete).
  • Bei den Parametern handelt es sich um die Schlüsselwerte für jeden Typ.The parameters will be the key value(s) for each type. Der Name jedes Parameters, der ** <type_name> _ <property_name> ** ist (z. b. Post_PostId und Tag_TagId).The name of each parameter being <type_name>_<property_name> (for example, Post_PostId and Tag_TagId).

Im folgenden finden Sie Beispiel gespeicherte Prozeduren zum Einfügen und aktualisieren.Here are example insert and update stored procedures.

CREATE PROCEDURE [dbo].[PostTag_Insert]  
  @Post_PostId int,  
  @Tag_TagId int  
AS  
  INSERT INTO [dbo].[Post_Tags] (Post_PostId, Tag_TagId)   
  VALUES (@Post_PostId, @Tag_TagId)
CREATE PROCEDURE [dbo].[PostTag_Delete]  
  @Post_PostId int,  
  @Tag_TagId int  
AS  
  DELETE FROM [dbo].[Post_Tags]    
  WHERE Post_PostId = @Post_PostId AND Tag_TagId = @Tag_TagId

Überschreiben der StandardwerteOverriding the Defaults

Die Prozedur-und Parameternamen können auf ähnliche Weise wie gespeicherte Prozeduren für Entitäten konfiguriert werden.The procedure and parameter names can be configured in a similar way to entity stored procedures.

modelBuilder  
  .Entity<Post>()  
  .HasMany(p => p.Tags)  
  .WithMany(t => t.Posts)  
  .MapToStoredProcedures(s =>  
    s.Insert(i => i.HasName("add_post_tag")  
                   .LeftKeyParameter(p => p.PostId, "post_id")  
                   .RightKeyParameter(t => t.TagId, "tag_id"))  
     .Delete(d => d.HasName("remove_post_tag")  
                   .LeftKeyParameter(p => p.PostId, "post_id")  
                   .RightKeyParameter(t => t.TagId, "tag_id")));