ストアド プロシージャのサポート (Entity Framework)

Entity Data Model (EDM) では、データの取得や変更のためにストアド プロシージャを使用できます。ストアド プロシージャを使用して、データを取得、挿入、更新、および削除することができます。

多くのデータベース アプリケーションでは、ストアド プロシージャに依存して次のような利点が提供されています。

  • セキュリティ。データベース ユーザーがテーブルやその他のデータベース オブジェクトに直接アクセスできないようにすることができます。データベース管理者は、ストアド プロシージャに対する実行権限を付与するだけで、データ アクセスのための単一のエントリ ポイントを作成できます。これにより、SQL インジェクション攻撃を受ける可能性を大幅に低減できます。入力パラメータと出力パラメータで既定値を使用するように構成すると、厳密なパラメータの検証を実現できます。ストアド プロシージャ内で検証コードを使用すると、使用可能なアクションを制限できます。

  • カプセル化。ストアド プロシージャを使用すると、複雑なデータ ロジック、明示的なトランザクション、およびその他のデータベース操作を 1 回記述するだけで複数のクライアント アプリケーションから実行できます。エラー、例外、および同時実行制御違反をサーバー側のコードで処理すると、クライアント アプリケーションからのラウンド トリップの回数を減らすことができます。ストアド プロシージャのコードを変更しても、ストアド プロシージャのシグネチャを変更しない限り、クライアント アプリケーションには影響しません。

  • 予測可能性。一般にデータベース管理者は、サーバーのパフォーマンスに悪影響を与える非効率なクエリがクライアント アプリケーションによって実行されないようにする必要があります。ストアド プロシージャでは、許容される実行プランが生成されるようにクエリを個別に調整できます。さらに、ストアド プロシージャを適切に記述すれば、ブロックやデッドロックなどのサーバー側の問題のトラブルシューティングも容易になります。

  • パフォーマンス。場合によっては、ストアド プロシージャを使用するとパフォーマンスが向上します。最近のデータベース エンジンでは、動的 SQL ステートメントがストアド プロシージャのステートメントと同程度の効率で処理されるのが一般的ですが、ストアド プロシージャの使用を強制すると、データベース管理者がパフォーマンスをより細かく制御できます。

データを返すストアド プロシージャは、EDM オブジェクト モデルで指定されている関数から呼び出されます。データを更新するストアド プロシージャはエンティティとアソシエーションにマップされ、そのストアド プロシージャが実装およびマップされていなかった場合にそこで定義されている操作によって使用されるシステム生成のメソッドの代わりに、暗黙的に呼び出されます。

ここでは、ModificationFunctionMapping スキーマ要素で指定されているマッピングを通じてデータを更新するために使用されるストアド プロシージャについて説明します。データを取得するストアド プロシージャでは FunctionImportMapping 要素が使用されます。データを取得するだけで変更しないストアド プロシージャのクイック スタート ガイドについては、「ストアド プロシージャを使用してモデルを定義する方法 (Entity Framework)」を参照してください。

ストアド プロシージャはその他に、既存エンティティ間のアソシエーションのインスタンスを挿入または削除するシナリオにも使用できます。これらの操作に対するストアド プロシージャのマッピングについては、「ストアド プロシージャへのアソシエーション セットのマッピング (Entity Framework)」を参照してください。

既定では、概念スキーマとストレージ スキーマのマッピングに基づいて直接 Entity Framework がデータベース テーブルに対して操作を実行します。ストアド プロシージャを使用してデータを更新するように Entity Framework を構成するには、ストレージ スキーマとマッピング スキーマを変更する必要があります。

次の表には、EDM でサポートされているいくつかのシナリオでストアド プロシージャを使用する方法に関するトピックへのリンクが含まれています。

操作 SSDL の要件 MSL の要件 CSDL の要件

エンティティ オブジェクトを返すクエリを実行する。詳細については、「ストアド プロシージャを使用してモデルを定義する方法 (Entity Framework)」を参照してください。

ストレージ モデル ファイルの Schema 要素に Function 要素を追加します。この要素は、エンティティ型を返すストアド プロシージャを参照します。

概念モデル ファイルの EntityContainerMapping 要素に FunctionImportMapping 要素を追加します。

概念モデル ファイルの EntityContainer 要素に FunctionImport 要素を追加します。

エンティティ データの挿入、更新、および削除にストアド プロシージャを使用する。詳細については、「変更ストアド プロシージャを使用してモデルを定義する方法 (Entity Framework)」を参照してください。

ストレージ モデル ファイルの Schema 要素に Function 要素を追加します。この操作を、挿入、更新、および削除の各ストアド プロシージャにつき 1 回ずつ実行します。

エンティティ型の EntityTypeMapping 要素に ModificationFunctionMapping 要素を追加します。この要素で、挿入、更新、および削除の各ストアド プロシージャの InsertFunctionUpdateFunction、および DeleteFunction の各要素を定義する必要があります。エンティティにリレーションシップがある場合は、AssociationEnd 要素でアソシエーションを指定します。

なし。

データ ソースでリンク テーブルを使用して実装されているエンティティ型間の多対多のリレーションシップを作成または削除するためにストアド プロシージャを使用する。詳細については、「ストアド プロシージャへのアソシエーション セットのマッピング (Entity Framework)」を参照してください。

ストレージ モデル ファイルの Schema 要素に Function 要素を追加します。この操作を、データ ソースでリレーションシップを作成または削除する各ストアド プロシージャにつき 1 回ずつ実行します。

アソシエーションの AssociationSetMapping Element 要素に ModificationFunctionMapping 要素を追加します。この要素で、そのアソシエーションのリレーションシップを作成および削除するストアド プロシージャの InsertFunction 要素と DeleteFunction 要素を定義する必要があります。

なし。

データの変更とストアド プロシージャ

データの変更に使用されるストアド プロシージャは、Entity Framework で生成されるメソッドを置き換えます。ストアド プロシージャは暗黙的に呼び出されるので、概念スキーマまたは既存のアプリケーション コードで定義された EDM への変更は不要です。

CSDL

次の概念スキーマ定義言語 (CSDL) セグメントでは、SalesOrderHeader エンティティと SalesOrderDetail エンティティを定義しています。どちらの型も、SQL Server 2005 および SQL Server 2008 に付属の AdventureWorks サンプル データベースに基づいています。ストアド プロシージャを使用して EDM データを変更するのに CSDL スキーマを変更する必要はありませんが、ここでは完全を期すために CSDL スキーマを示しています。このスキーマは、わかりやすくするために一部のプロパティの定義が省略されています。完全なスキーマについては、「AdventureWorks Sales Model (EDM)」のサンプルを参照してください。

      <Schema Namespace="AdventureWorksModel" 
              Alias="Self" xmlns="https://schemas.microsoft.com/ado/2006/04/edm">
        <EntityContainer Name="AdventureWorksEntities">
          <EntitySet Name="AddressType" EntityType="AdventureWorksModel.AddressType" />
          <EntitySet Name="Contact" EntityType="AdventureWorksModel.Contact" />
          <EntitySet Name="Product" EntityType="AdventureWorksModel.Product" />
          <EntitySet Name="SalesOrderDetail" 
                     EntityType="AdventureWorksModel.SalesOrderDetail" />
          <EntitySet Name="SalesOrderHeader" 
                     EntityType="AdventureWorksModel.SalesOrderHeader" />
          <AssociationSet Name="FK_SalesOrderHeader_Contact_ContactID"
Association="AdventureWorksModel.FK_SalesOrderHeader_Contact_ContactID">
            <End Role="Contact" EntitySet="Contact" />
            <End Role="SalesOrderHeader" EntitySet="SalesOrderHeader" />
          </AssociationSet>
          <AssociationSet Name="FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID" 
Association="AdventureWorksModel.FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID">
            <End Role="SalesOrderHeader" EntitySet="SalesOrderHeader" />
            <End Role="SalesOrderDetail" EntitySet="SalesOrderDetail" />
          </AssociationSet>

        </EntityContainer>

        
        <EntityType Name="SalesOrderDetail">
          <Key>
            <PropertyRef Name="SalesOrderID" />
            <PropertyRef Name="SalesOrderDetailID" />
          </Key>
          <Property Name="SalesOrderID" Type="Int32" Nullable="false" />
          <Property Name="SalesOrderDetailID"
                             Type="Int32" Nullable="false" />
          <Property Name="CarrierTrackingNumber" Type="String" />
          <Property Name="OrderQty" Type="Int16" Nullable="false" />
          <Property Name="ProductID" Type="Int32" Nullable="false" />
          <Property Name="SpecialOfferID" Type="Int32" Nullable="false" />
          <Property Name="UnitPrice" Type="Decimal" Nullable="false" />
          <Property Name="UnitPriceDiscount"
                             Type="Decimal" Nullable="false" />
          <Property Name="LineTotal" Type="Decimal" Nullable="false" />
          <Property Name="rowguid" Type="Guid" Nullable="false" />
          <Property Name="ModifiedDate"
                             Type="DateTime" Nullable="false" />
          <NavigationProperty Name="SalesOrderHeader"
Relationship="AdventureWorksModel.FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID"
             FromRole="SalesOrderDetail" ToRole="SalesOrderHeader" />
        </EntityType>

        <EntityType Name="SalesOrderHeader">
          <Key>
            <PropertyRef Name="SalesOrderID" />
          </Key>
          <Property Name="SalesOrderID" Type="Int32" Nullable="false" />
          <Property Name="RevisionNumber" Type="Byte" Nullable="false" />
          <Property Name="OrderDate" Type="DateTime" Nullable="false" />
          <Property Name="DueDate" Type="DateTime" Nullable="false" />
          <Property Name="ShipDate" Type="DateTime" />
          <Property Name="Status" Type="Byte" Nullable="false" />
          <Property Name="OnlineOrderFlag"
                        Type="Boolean" Nullable="false" />
          <Property Name="SalesOrderNumber"
                        Type="String" Nullable="false" />
          <Property Name="PurchaseOrderNumber" Type="String" />
          <Property Name="AccountNumber" Type="String" />
          <Property Name="CustomerID" Type="Int32" Nullable="false" />
          <Property Name="SalesPersonID" Type="Int32" />
          <Property Name="TerritoryID" Type="Int32" />
          <Property Name="BillToAddressID"
                        Type="Int32" Nullable="false" />
          <Property Name="ShipToAddressID"
                        Type="Int32" Nullable="false" />
          <Property Name="ShipMethodID" Type="Int32" Nullable="false" />
          <Property Name="CreditCardID" Type="Int32" />
          <Property Name="CreditCardApprovalCode" Type="String" />
          <Property Name="CurrencyRateID" Type="Int32" />
          <Property Name="SubTotal" Type="Decimal" Nullable="false" />
          <Property Name="TaxAmt" Type="Decimal" Nullable="false" />
          <Property Name="Freight" Type="Decimal" Nullable="false" />
          <Property Name="TotalDue" Type="Decimal" Nullable="false" />
          <Property Name="Comment" Type="String" />
          <Property Name="rowguid" Type="Guid" Nullable="false" />
          <Property Name="ModifiedDate" Type="DateTime" Nullable="false" />
          <NavigationProperty Name="Contact" 
Relationship="AdventureWorksModel.FK_SalesOrderHeader_Contact_ContactID"
            FromRole="SalesOrderHeader" ToRole="Contact" />
          <NavigationProperty Name="SalesOrderDetail"
Relationship="AdventureWorksModel.FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID"
            FromRole="SalesOrderHeader" ToRole="SalesOrderDetail" />
        </EntityType>

        <EntityType Name="AddressType">
          <Key>
            <PropertyRef Name="AddressTypeID" />
          </Key>
          <!-- Other properties -->
        </EntityType>

        <EntityType Name="Contact">
          <Key>
            <PropertyRef Name="ContactID" />
          </Key>
          <!-- Other properties -->
          <NavigationProperty Name="SalesOrderHeader"
Relationship="AdventureWorksModel.FK_SalesOrderHeader_Contact_ContactID" 
            FromRole="Contact" ToRole="SalesOrderHeader" />
        </EntityType>

        <EntityType Name="Product">
          <Key>
            <PropertyRef Name="ProductID" />
          </Key>
          <!-- Other properties -->
        </EntityType>


        <Association Name="FK_SalesOrderHeader_Contact_ContactID">
          <End Role="Contact" 
              Type="AdventureWorksModel.Contact" Multiplicity="1" />
          <End Role="SalesOrderHeader"
        Type="AdventureWorksModel.SalesOrderHeader" Multiplicity="*" />
        </Association>

        <Association Name="FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID">
          <End Role="SalesOrderHeader"
          Type="AdventureWorksModel.SalesOrderHeader" Multiplicity="1">
            <OnDelete Action="Cascade" />
          </End>
          <End Role="SalesOrderDetail"
           Type="AdventureWorksModel.SalesOrderDetail" Multiplicity="*" />
          <ReferentialConstraint>
            <Principal Role="SalesOrderHeader">
              <PropertyRef Name="SalesOrderID" />
            </Principal>
            <Dependent Role="SalesOrderDetail">
              <PropertyRef Name="SalesOrderID" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
      </Schema>

CSDL の詳細については、「概念スキーマ (CSDL)」を参照してください。

例で使用されているストアド プロシージャ

ストアド プロシージャを実際に使用してみることができるように、AdventureWorks データベースを変更する以下のデータベース スクリプトが用意されています。これらのスクリプトは、ストレージ内の SalesOrderDetail のインスタンスを作成、更新、および削除するストアド プロシージャを作成します。

[!メモ]

Entity Framework データによって使用されるストアド プロシージャの内部でトランザクション管理を使用すると、Entity Framework の処理と競合する可能性があるため、使用しないようにすることをお勧めします。

CreateSalesOrderDetail プロシージャ

次のスクリプトは、ストレージに SalesOrderDetail 項目を追加するストアド プロシージャを作成します。このスクリプトには、この例を試した後に必要に応じてストアド プロシージャを削除できるコードが含まれています。ストアド プロシージャを削除するには、drop procedure より後の行を省略してスクリプトを実行します。

USE [AdventureWorks]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID ( 'dbo.CreateSalesOrderDetail', 'P' ) IS NOT NULL 
DROP PROCEDURE dbo.CreateSalesOrderDetail;
GO

CREATE PROCEDURE [dbo].[CreateSalesOrderDetail] 
   @SalesOrderID int,
   @CarrierTrackingNumber nvarchar(25),
   @OrderQty smallint,
   @ProductID int,
   @SpecialOfferID int,
   @UnitPrice money,
   @UnitPriceDiscount money,
   @rowguid uniqueidentifier,
   @ModifiedDate datetime
   
AS

INSERT INTO [AdventureWorks].[Sales].[SalesOrderDetail]
           ([SalesOrderID]
           ,[CarrierTrackingNumber]
           ,[OrderQty]
           ,[ProductID]
           ,[SpecialOfferID]
           ,[UnitPrice]
           ,[UnitPriceDiscount]
           ,[rowguid]
           ,[ModifiedDate])
     VALUES
           (@SalesOrderID,
           @CarrierTrackingNumber,
           @OrderQty,
           @ProductID,
           @SpecialOfferID,
           @UnitPrice,
           @UnitPriceDiscount,
           @rowguid,
           @ModifiedDate)

select SalesOrderDetailID, LineTotal
 from [AdventureWorks].[Sales].[SalesOrderDetail]
 where SalesOrderID = @SalesOrderID and SalesOrderDetailID = scope_identity()

UpdateSalesOrderDetail プロシージャ

次のスクリプトは、ストレージ内の SalesOrderDetail 項目を更新するためのストアド プロシージャを作成します。

USE [AdventureWorks]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID ( 'dbo.UpdateSalesOrderDetail', 'P' ) IS NOT NULL 
DROP PROCEDURE dbo.UpdateSalesOrderDetail;
GO

CREATE PROCEDURE [dbo].[UpdateSalesOrderDetail]
   @OrderQty smallint, 
   @SalesOrderDetailID int,
   @SalesOrderID int

AS
UPDATE [AdventureWorks].[Sales].[SalesOrderDetail]
   SET [OrderQty] = @OrderQty
 WHERE SalesOrderDetailID = @SalesOrderDetailID

DeleteSalesOrderDetail プロシージャ

次のスクリプトは、ストレージ内の SalesOrderDetail 項目を削除するためのストアド プロシージャを作成します。

USE [AdventureWorks]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID ( 'dbo.DeleteSalesOrderDetail', 'P' ) IS NOT NULL 
DROP PROCEDURE dbo.DeleteSalesOrderDetail;
GO

CREATE PROCEDURE [dbo].[DeleteSalesOrderDetail] 
   @SalesOrderDetailID int,
   @SalesOrderID int 
AS
DELETE FROM [AdventureWorks].[Sales].[SalesOrderDetail]
      WHERE SalesOrderDetailID = @SalesOrderDetailID

ストア スキーマ定義言語 (SSDL)

ストレージ スキーマでは、データベースで使用できるストアド プロシージャを Function 要素で定義し、マップできるストアド プロシージャのパラメータの名前を入れ子になった Parameter 要素で指定します。これらの宣言により、データベース内にストアド プロシージャが存在することが Entity Framework に通知されますが、マッピングは指定されません。マッピングは、後ほど説明するマッピング スキーマで実装されます。

ストアド プロシージャを表す関数宣言の IsComposable 属性は false に設定する必要があります。この設定は、プロシージャから返される結果を他の Entity SQL ステートメントの FROM 句で使用できないということを示します。次のストレージ スキーマの宣言では、CreateSalesOrderDetailUpdateSalesOrderDetail、および DeleteSalesOrderDetail の 3 つのストアド プロシージャを指定しています。

        <Function Name="CreateSalesOrderDetail" Aggregate="false"
                  BuiltIn="false" NiladicFunction="false"
                  IsComposable="false"
                  ParameterTypeSemantics="AllowImplicitConversion"
                  Schema="dbo">
          <Parameter Name="SalesOrderID" Type="int" Mode="In" />
          <Parameter Name="CarrierTrackingNumber" Type="nvarchar" Mode="In" />
          <Parameter Name="OrderQty" Type="smallint" Mode="In" />
          <Parameter Name="ProductID" Type="int" Mode="In" />
          <Parameter Name="SpecialOfferID" Type="int" Mode="In" />
          <Parameter Name="UnitPrice" Type="money" Mode="In" />
          <Parameter Name="UnitPriceDiscount" Type="money" Mode="In" />
          <Parameter Name="rowguid" Type="uniqueidentifier" Mode="In" />
          <Parameter Name="ModifiedDate" Type="datetime" Mode="In" />
        </Function>

        <Function Name="UpdateSalesOrderDetail" Aggregate="false"
                  BuiltIn="false" NiladicFunction="false"
                  IsComposable="false"
                  ParameterTypeSemantics="AllowImplicitConversion"
                  Schema="dbo">
          <Parameter Name="OrderQty" Type="smallint" Mode="In"/>
          <Parameter Name="SalesOrderDetailID" Type="int" Mode="In"/>
          <Parameter Name="SalesOrderID" Type="int" Mode="In"/>
        </Function>

        <Function Name="DeleteSalesOrderDetail" Aggregate="false"
                  BuiltIn="false" NiladicFunction="false"
                  IsComposable="false"
                  ParameterTypeSemantics="AllowImplicitConversion"
                  Schema="dbo">
          <Parameter Name="SalesOrderDetailID" Type="int" Mode="In"/>
          <Parameter Name="SalesOrderID" Type="int" Mode="In"/>
        </Function>

ストアド プロシージャを追加する前の AdventureWorks Sales Model の完全なストレージ スキーマについては、「AdventureWorks Sales ストレージ スキーマ (EDM)」を参照してください。

マッピング スキーマ言語 (MSL)

マッピング スキーマでは、ストレージ スキーマで宣言されている関数とデータベースのストアド プロシージャとのマッピングを定義します。

EntitySetMappingEntityTypeMapping 要素の下にある ModificationFunctionMapping 要素は、SSDL ファイルで指定されているどの関数で変更処理を行うかを記述します。子要素には、DeleteFunctionInsertFunction、および UpdateFunction があります。各関数マッピングは、マップされるストアド プロシージャの FunctionName を指定します。

EntityTypeMapping 内の AssociationEnd 要素では、リレーションシップを参照 (外部キー) として扱うことができます。これが、エンティティを別のエンティティに関連付けるアソシエーションの基礎になります。既存エンティティ間のアソシエーションのストアド プロシージャによる作成または削除については、「ストアド プロシージャへのアソシエーション セットのマッピング (Entity Framework)」を参照してください。

  <ModificationFunctionMapping >
    <InsertFunction
       FunctionName="AdventureWorksModel.Store.CreateSalesOrderDetail">
        <ScalarProperty Name="CarrierTrackingNumber"
              ParameterName="CarrierTrackingNumber" Version="Current"/>
        <ScalarProperty Name="OrderQty" ParameterName="OrderQty"
              Version="Current"/>
        <ScalarProperty Name="ProductID" ParameterName="ProductID" Version="Current"/>
         <ScalarProperty Name="SpecialOfferID"
              ParameterName="SpecialOfferID" Version="Current"/>
        <ScalarProperty Name="UnitPrice" 
              ParameterName="UnitPrice" Version="Current"/>
        <ScalarProperty Name="UnitPriceDiscount"
              ParameterName="UnitPriceDiscount" Version="Current"/>
        <ScalarProperty Name="rowguid" ParameterName="rowguid"
              Version="Current"/>
        <ScalarProperty Name="ModifiedDate"
              ParameterName="ModifiedDate" Version="Current"/>
        <AssociationEnd
           AssociationSet="FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID"
          From="SalesOrderDetail" To="SalesOrderHeader">
        <ScalarProperty Name="SalesOrderID"
                   ParameterName="SalesOrderID" />
        </AssociationEnd>
        <ResultBinding ColumnName="SalesOrderDetailID"
                   Name="SalesOrderDetailID" />
         <ResultBinding ColumnName="LineTotal" Name="LineTotal" />
  </InsertFunction>

    <UpdateFunction
    FunctionName="AdventureWorksModel.Store.UpdateSalesOrderDetail" >
        <ScalarProperty Name="OrderQty" ParameterName="OrderQty"
             Version="Current"/>
        <ScalarProperty Name="SalesOrderDetailID"
           ParameterName="SalesOrderDetailID" Version="Current"/>
        <AssociationEnd
    AssociationSet="FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID"
       From="SalesOrderDetail" To="SalesOrderHeader">
          <ScalarProperty Name="SalesOrderID"
            ParameterName="SalesOrderID" Version="Current" />
        </AssociationEnd>
    </UpdateFunction>

    <DeleteFunction
     FunctionName="AdventureWorksModel.Store.DeleteSalesOrderDetail" >
        <ScalarProperty Name="SalesOrderDetailID"
           ParameterName="SalesOrderDetailID" Version="Original"/>
        <AssociationEnd
           AssociationSet="FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID"
          From="SalesOrderDetail" To="SalesOrderHeader">
        <ScalarProperty Name="SalesOrderID"
                  ParameterName="SalesOrderID" />
        </AssociationEnd>
    </DeleteFunction>
  </ModificationFunctionMapping>

ストアド プロシージャを追加する前の AdventureWorks モデルのマッピング スキーマについては、「AdventureWorks Sales マッピング スキーマ (EDM)」を参照してください。

オプティミスティック同時実行制御

ScalarProperty 要素の Version 属性を使用すると、更新および削除でオプティミスティック同時実行制御を使用できます。Version 属性では、original (データベースから読み取った元のデータ) または current (クライアント コードによって変更された可能性があるデータ) のいずれかの値を指定できます。バージョンの指定は、更新関数のマッピングでは必須ですが、削除関数のマッピングでは省略可能です。挿入の場合は、データ ソースに対してテストする元の値がないため、オプティミスティック同時実行制御は必要ありません。

Version 属性を設定すると、オプティミスティック同時実行制御を実行する際にストアド プロシージャで古い値と新しい値の両方をパラメータとして受け取ることができます。これにより、アプリケーションで最後にデータ ソースから取得した値と同じ値がまだデータ ソースで保持されている場合にのみ更新や削除が行われるようにすることができます。

エンティティ プロパティの元のバージョンにバインドされた入力パラメータは、ストアド プロシージャの UPDATE ステートメントや DELETE ステートメントの WHERE 句で使用されます。更新の場合は、エンティティ プロパティの現在のバージョンにバインドされた追加のパラメータがストアド プロシージャの UPDATE ステートメントの SET 句で使用されます。これにより、元の値がまだデータ ソースの値と一致する場合にのみ新しい (現在の) 値がデータ ソースに割り当てられます。元の値を取得した後に他のユーザーやアプリケーションによってデータ ソースの値が変更されていた場合は更新や削除が失敗します。

サーバーの値の取得

挿入と更新では、追加の子要素 ResultBinding により、サーバーで生成された値を結果セットから取得できます。ResultBinding 要素では、戻り値とエンティティ プロパティとの対応関係を指定します。これにより、更新パイプラインで値を概念モデルに基づいてオブジェクトに設定できます。

ResultBinding 要素には、参照先エンティティ定義のプロパティの名前である Name 属性と、ストアド プロシージャから返される結果セットの列の名前である ColumnName 属性があります。次のスキーマ セグメントは ResultBinding 要素を示しています。

    <ResultBinding Name="SalesOrderDetailID"
                    ColumnName="SalesOrderDetailID" />
    <ResultBinding Name="LineTotal" ColumnName="LineTotal" />
  </InsertFunction>

ストアド プロシージャのコードでは、INSERT ステートメントまたは UPDATE ステートメントの実行後に SELECT ステートメントを使用して、ResultBinding に渡された値を取得します。

SELECT SalesOrderDetailID, LineTotal
  FROM [AdventureWorks].[Sales].[SalesOrderDetail]
  WHERE SalesOrderID = @SalesOrderID and SalesOrderDetailID = scope_identity()

参照

処理手順

ストアド プロシージャを使用してモデルを定義する方法 (Entity Framework)

概念

ModificationFunctionMapping (EntityTypeMapping)
ModificationFunctionMapping (AssociationSetMapping)
Entity Framework のリソース
Entity Framework の用語
ストアド プロシージャへのアソシエーション セットのマッピング (Entity Framework)

その他のリソース

EDM 仕様
スキーマおよびマッピング スキーマ (Entity Framework)
チュートリアル : ストアド プロシージャへのエンティティのマッピング