将关联集映射到存储过程(实体框架)
AssociationSetMapping 内的 ModificationFunctionMapping 元素指定在实体框架中插入和删除实体之间的关联实例的存储过程。当映射多对多关联(数据库中的链接表通常支持这种关联)时,AssociationSetMapping 中的 ModificationFunctionMapping 会十分有用。
当映射外键关系(如 AdventureWorks 示例数据库中的 SalesOrderDetail
与 SalesOrderHeader
之间的关系)时,可在 ModificationFunctionMappingEntityTypeMapping 中使用 AssociationEnd 绑定技术。有关更多信息,请参见存储过程支持(实体框架)。
AssociationSetMapping 中的顶级元素为 ModificationFunctionMapping 元素。DeleteFunction 和 InsertFunction 子元素描述关联两端的参数绑定。
DeleteFunction 和 InsertFunction 的 FunctionName 属性是它们各自在存储模型中引用的存储过程的名称。
注意 |
---|
关联集不存在 UpdateFunction 元素,原因是关联不可修改,只可创建或删除。 |
在关联集的存储过程映射中声明的 EndProperty 绑定类似于在 EntitySetMapping 中声明的 AssociationEnd 元素,但是这些绑定需要的上下文较少,因为父元素指示的是 AssociationSet。ScalarProperty 子元素描述关联两端的键值与存储过程的对应参数的参数绑定。
下面的示例映射插入和删除函数,这些函数在支持 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 架构已经过手动修改,实现了 AssociationSetMapping 和 ModificationFunctionMapping。实体框架设计器工具不支持 ModificationFunctionMapping 的 AssociationSetMapping 的实现。
<?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)