将关联集映射到存储过程(实体框架)

AssociationSetMapping 内的 ModificationFunctionMapping 元素指定在实体框架中插入和删除实体之间的关联实例的存储过程。当映射多对多关联(数据库中的链接表通常支持这种关联)时,AssociationSetMapping 中的 ModificationFunctionMapping 会十分有用。

当映射外键关系(如 AdventureWorks 示例数据库中的 SalesOrderDetailSalesOrderHeader 之间的关系)时,可在 ModificationFunctionMappingEntityTypeMapping 中使用 AssociationEnd 绑定技术。有关更多信息,请参见存储过程支持(实体框架)

AssociationSetMapping 中的顶级元素为 ModificationFunctionMapping 元素。DeleteFunctionInsertFunction 子元素描述关联两端的参数绑定。

DeleteFunctionInsertFunctionFunctionName 属性是它们各自在存储模型中引用的存储过程的名称。

Note注意

关联集不存在 UpdateFunction 元素,原因是关联不可修改,只可创建或删除。

在关联集的存储过程映射中声明的 EndProperty 绑定类似于在 EntitySetMapping 中声明的 AssociationEnd 元素,但是这些绑定需要的上下文较少,因为父元素指示的是 AssociationSetScalarProperty 子元素描述关联两端的键值与存储过程的对应参数的参数绑定。

下面的示例映射插入和删除函数,这些函数在支持 Contact_Address 关联的多对多链接表中创建和删除项。

  <AssociationSetMapping Name="Contact_Address"
                TypeName="ContactInformationModel.Contact_Address"
                StoreEntitySet="Contact_Address">
    <EndProperty Name="Address">
      <ScalarProperty Name="AddressID" ColumnName="AddressID" />
    </EndProperty>
    <EndProperty Name="Contact">
      <ScalarProperty Name="ContactID" ColumnName="ContactID" />
    </EndProperty>
    <ModificationFunctionMapping>
      <DeleteFunction
        FunctionName="ContactInformationModel.Store.DeleteAddress">
        <EndProperty Name="Address">
          <ScalarProperty Name="AddressID" ParameterName="AddressID"/>
        </EndProperty>
        <EndProperty Name="Contact">
          <ScalarProperty Name="ContactID" ParameterName="ContactID"/>
        </EndProperty>
      </DeleteFunction>
      <InsertFunction
        FunctionName="ContactInformationModel.Store.SetAddress">
        <EndProperty Name="Address">
          <ScalarProperty Name="AddressID" ParameterName="AddressID"/>
        </EndProperty>
        <EndProperty Name="Contact">
          <ScalarProperty Name="ContactID" ParameterName="ContactID"/>
        </EndProperty>
      </InsertFunction>
    </ModificationFunctionMappi

若要创建此示例中使用的数据库,请运行下面的脚本。

USE [master]
GO
CREATE DATABASE [ContactInformation]
GO
USE [ContactInformation]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Address]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Address](
    [AddressID] [int] NOT NULL,
    [StreetAddress] [nvarchar](50) NOT NULL,
    [City] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED 
(
[AddressID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Contact]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Contact](
    [ContactID] [int] NOT NULL,
    [LastName] [nvarchar](50) NOT NULL,
    [FirstName] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Contact] PRIMARY KEY CLUSTERED 
(
    [ContactID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Contact_Address]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Contact_Address](
    [ContactID] [int] NOT NULL,
    [AddressID] [int] NOT NULL
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Address]') AND parent_object_id = OBJECT_ID(N'[dbo].[Contact_Address]'))
ALTER TABLE [dbo].[Contact_Address]  WITH CHECK ADD  CONSTRAINT [FK_Address] FOREIGN KEY([AddressID])
REFERENCES [dbo].[Address] ([AddressID])
GO
ALTER TABLE [dbo].[Contact_Address] CHECK CONSTRAINT [FK_Address]
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Contact]') AND parent_object_id = OBJECT_ID(N'[dbo].[Contact_Address]'))
ALTER TABLE [dbo].[Contact_Address]  WITH CHECK ADD  CONSTRAINT [FK_Contact] FOREIGN KEY([ContactID])
REFERENCES [dbo].[Contact] ([ContactID])
GO
ALTER TABLE [dbo].[Contact_Address] CHECK CONSTRAINT [FK_Contact]

若要创建此示例中使用的存储过程,请运行下面的脚本。

使用下面的脚本可创建用于创建关联实例的函数:

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

CREATE PROCEDURE [dbo].[SetAddress] 
    @ContactID int,
    @AddressID int
AS
INSERT Contact_Address(ContactID, AddressID)
  VALUES(@ContactID, @AddressID)

使用下面的脚本可创建用于删除关联实例的函数:

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

CREATE PROCEDURE [dbo].[DeleteAddress] 
    @ContactID int,
    @AddressID int
AS

Delete Contact_Address
  WHERE ContactID = @ContactID 
  AND AddressID = @AddressID

下面演示的完整 .edmx 架构已经过手动修改,实现了 AssociationSetMappingModificationFunctionMapping。实体框架设计器工具不支持 ModificationFunctionMappingAssociationSetMapping 的实现。

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0"
           xmlns:edmx="https://schemas.microsoft.com/ado/2007/06/edmx">
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="ContactInformationModel.Store" Alias="Self"
           Provider="System.Data.SqlClient" ProviderManifestToken="2005"
           xmlns:store="https://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
           xmlns="https://schemas.microsoft.com/ado/2006/04/edm/ssdl">
        <EntityContainer Name="dbo">
          <EntitySet Name="Address"
                     EntityType="ContactInformationModel.Store.Address"
                     store:Type="Tables" />
          <EntitySet Name="Contact"
                     EntityType="ContactInformationModel.Store.Contact"
                     store:Type="Tables" />
          <EntitySet Name="Contact_Address"
                     EntityType="ContactInformationModel.Store.Contact_Address"
                     store:Type="Tables" store:Schema="dbo" 
                           store:Name="Contact_Address">
            <DefiningQuery>
              SELECT
              [Contact_Address].[ContactID] AS [ContactID],
              [Contact_Address].[AddressID] AS [AddressID]
              FROM [dbo].[Contact_Address] AS [Contact_Address]
            </DefiningQuery>
          </EntitySet>
          <AssociationSet Name="FK_Address"
                          Association="ContactInformationModel.Store.FK_Address">
            <End Role="Address" EntitySet="Address" />
            <End Role="Contact_Address" EntitySet="Contact_Address" />
          </AssociationSet>
          <AssociationSet Name="FK_Contact"
                          Association="ContactInformationModel.Store.FK_Contact">
            <End Role="Contact" EntitySet="Contact" />
            <End Role="Contact_Address" EntitySet="Contact_Address" />
          </AssociationSet>
        </EntityContainer>
        <EntityType Name="Address">
          <Key>
            <PropertyRef Name="AddressID" />
          </Key>
          <Property Name="AddressID" Type="int" Nullable="false" />
          <Property Name="StreetAddress" Type="nvarchar"
                    Nullable="false" MaxLength="50" />
          <Property Name="City" Type="nvarchar"
                    Nullable="false" MaxLength="50" />
        </EntityType>
        <EntityType Name="Contact">
          <Key>
            <PropertyRef Name="ContactID" />
          </Key>
          <Property Name="ContactID" Type="int" Nullable="false" />
          <Property Name="LastName" Type="nvarchar"
                    Nullable="false" MaxLength="50" />
          <Property Name="FirstName" Type="nvarchar"
                    Nullable="false" MaxLength="50" />
        </EntityType>

        <EntityType Name="Contact_Address">
          <Key>
            <PropertyRef Name="ContactID" />
            <PropertyRef Name="AddressID" />
          </Key>
          <Property Name="ContactID" Type="int" Nullable="false" />
          <Property Name="AddressID" Type="int" Nullable="false" />
        </EntityType>
        <Association Name="FK_Address">
          <End Role="Address"
                   Type="ContactInformationModel.Store.Address"
               Multiplicity="1" />
          <End Role="Contact_Address"
               Type="ContactInformationModel.Store.Contact_Address"
               Multiplicity="*" />
          <ReferentialConstraint>
            <Principal Role="Address">
              <PropertyRef Name="AddressID" />
            </Principal>
            <Dependent Role="Contact_Address">
              <PropertyRef Name="AddressID" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
        <Association Name="FK_Contact">
          <End Role="Contact"
                   Type="ContactInformationModel.Store.Contact"
               Multiplicity="1" />
          <End Role="Contact_Address"
               Type="ContactInformationModel.Store.Contact_Address"
               Multiplicity="*" />
          <ReferentialConstraint>
            <Principal Role="Contact">
              <PropertyRef Name="ContactID" />
            </Principal>
            <Dependent Role="Contact_Address">
              <PropertyRef Name="ContactID" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
        <Function Name="DeleteAddress" 
                            Aggregate="false" BuiltIn="false"
                  NiladicFunction="false" IsComposable="false"
                  ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
          <Parameter Name="ContactID" Type="int" Mode="In" />
          <Parameter Name="AddressID" Type="int" Mode="In" />
        </Function>
        <Function Name="SetAddress" Aggregate="false" BuiltIn="false"
                  NiladicFunction="false" IsComposable="false"
                  ParameterTypeSemantics="AllowImplicitConversion"
                                                        Schema="dbo">
          <Parameter Name="ContactID" Type="int" Mode="In" />
          <Parameter Name="AddressID" Type="int" Mode="In" />
        </Function>
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="ContactInformationModel" Alias="Self"
              xmlns="https://schemas.microsoft.com/ado/2006/04/edm">
        <EntityContainer Name="ContactInformationEntities">
          <EntitySet Name="Addresses"
                     EntityType="ContactInformationModel.Address" />
          <EntitySet Name="Contacts"
                     EntityType="ContactInformationModel.Contact" />
          <AssociationSet Name="Contact_Address"
            Association="ContactInformationModel.Contact_Address">
            <End Role="Address" EntitySet="Addresses" />
            <End Role="Contact" EntitySet="Contacts" />
          </AssociationSet>
        </EntityContainer>
        <EntityType Name="Address">
          <Key>
            <PropertyRef Name="AddressID" />
          </Key>
          <Property Name="AddressID" Type="Int32" Nullable="false" />
          <Property Name="StreetAddress" Type="String" Nullable="false"
                    MaxLength="50" Unicode="true" FixedLength="false" />
          <Property Name="City" Type="String" Nullable="false"
                    MaxLength="50" Unicode="true" FixedLength="false" />
          <NavigationProperty Name="Contact"
            Relationship="ContactInformationModel.Contact_Address"
                    FromRole="Address" ToRole="Contact" />
        </EntityType>
        <EntityType Name="Contact">
          <Key>
            <PropertyRef Name="ContactID" />
          </Key>
          <Property Name="ContactID" Type="Int32" Nullable="false" />
          <Property Name="LastName" Type="String" Nullable="false"
                    MaxLength="50" Unicode="true" FixedLength="false" />
          <Property Name="FirstName" Type="String" Nullable="false"
                    MaxLength="50" Unicode="true" FixedLength="false" />
          <NavigationProperty Name="Address"
             Relationship="ContactInformationModel.Contact_Address"
                    FromRole="Contact" ToRole="Address" />
        </EntityType>
        <Association Name="Contact_Address">
          <End Role="Address"
               Type="ContactInformationModel.Address" Multiplicity="*" />
          <End Role="Contact"
               Type="ContactInformationModel.Contact" Multiplicity="*" />
        </Association>
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S"
               xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
        <EntityContainerMapping StorageEntityContainer="dbo"
                 CdmEntityContainer="ContactInformationEntities">
          <EntitySetMapping Name="Addresses">
            <EntityTypeMapping
                 TypeName="IsTypeOf(ContactInformationModel.Address)">
              <MappingFragment StoreEntitySet="Address">
                <ScalarProperty Name="AddressID" ColumnName="AddressID" />
                <ScalarProperty Name="StreetAddress"
                              ColumnName="StreetAddress" />
                <ScalarProperty Name="City" ColumnName="City" />
              </MappingFragment>
            </EntityTypeMapping>
          </EntitySetMapping>
          <EntitySetMapping Name="Contacts">
            <EntityTypeMapping
              TypeName="IsTypeOf(ContactInformationModel.Contact)">
              <MappingFragment StoreEntitySet="Contact">
                <ScalarProperty Name="ContactID" ColumnName="ContactID" />
                <ScalarProperty Name="LastName" ColumnName="LastName" />
                <ScalarProperty Name="FirstName" ColumnName="FirstName" />
              </MappingFragment>
            </EntityTypeMapping>
          </EntitySetMapping>
          <AssociationSetMapping Name="Contact_Address"
             TypeName="ContactInformationModel.Contact_Address"
                        StoreEntitySet="Contact_Address">
            <EndProperty Name="Address">
              <ScalarProperty Name="AddressID" ColumnName="AddressID" />
            </EndProperty>
            <EndProperty Name="Contact">
              <ScalarProperty Name="ContactID" ColumnName="ContactID" />
            </EndProperty>
            <ModificationFunctionMapping>
              <DeleteFunction
         FunctionName="ContactInformationModel.Store.DeleteAddress">
                <EndProperty Name="Address">
                  <ScalarProperty Name="AddressID"
                                 ParameterName="AddressID"/>
                </EndProperty>
                <EndProperty Name="Contact">
                  <ScalarProperty Name="ContactID"
                                 ParameterName="ContactID"/>
                </EndProperty>
              </DeleteFunction>
              <InsertFunction
       FunctionName="ContactInformationModel.Store.SetAddress">
                <EndProperty Name="Address">
                  <ScalarProperty Name="AddressID"
                               ParameterName="AddressID"/>
                </EndProperty>
                <EndProperty Name="Contact">
                  <ScalarProperty Name="ContactID"
                               ParameterName="ContactID"/>
                </EndProperty>
              </InsertFunction>
            </ModificationFunctionMapping>
          </AssociationSetMapping>
        </EntityContainerMapping>
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>
  <edmx:Designer xmlns="https://schemas.microsoft.com/ado/2007/06/edmx">
    <edmx:Connection>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
      </DesignerInfoPropertySet>
    </edmx:Connection>
    <edmx:Options>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="ValidateOnBuild" Value="true" />
      </DesignerInfoPropertySet>
    </edmx:Options>
    <edmx:Diagrams >
<Diagram Name="ContactInformation">
<EntityTypeShape EntityType="ContactInformationModel.Address" PointX="0.75" PointY="0.875" Width="1.5" Height="1.787985026041667" IsExpanded="true" />
<EntityTypeShape EntityType="ContactInformationModel.Contact" PointX="3" PointY="0.875" Width="1.5" Height="1.787985026041667" IsExpanded="true" />
<AssociationConnector Association="ContactInformationModel.Contact_Address" ManuallyRouted="false">
<ConnectorPoint PointX="2.25" PointY="1.7689925130208335" />
<ConnectorPoint PointX="3" PointY="1.7689925130208335" />
</AssociationConnector>
</Diagram>
</edmx:Diagrams>
  </edmx:Designer>

另请参见

任务

如何:使用存储过程定义模型(实体框架)
如何:使用存储过程执行查询(实体框架)

概念

存储过程支持(实体框架)
ModificationFunctionMapping (AssociationSetMapping)
ModificationFunctionMapping (EntityTypeMapping)