Implementieren von Zuordnungen (EDM)
In Entitätsdatenmodell (EDM) werden Zuordnungen in der konzeptionellen Schemadefinitionssprache (CSDL) definiert. Bei der Implementierung von Zuordnungen werden die Definitionen in CSDL den Speichermetadaten zugeordnet. Die Zuordnungen werden vom selben Schema erstellt, das die Entitäten definiert, denen sie zugeordnet sind.
In diesem Thema sowie im Thema Anwendungscode mit Zuordnungen (EDM) wird mithilfe eines einfachen End-to-End-Beispiels erläutert, wie die Zuordnungen dem Speicher zugeordnet und im Code initialisiert werden und wie die Zuordnungsdaten von einer Anwendung navigiert werden.
Zuordnen von Kunden, Aufträgen und Auftragspositionen
In Geschäftsbereichsanwendungen stehen die Entitäten, die Kunden und Aufträge darstellen, in einer logischen Beziehung zueinander. Die von den Kunden erworbenen Produkte sind in den Aufträgen dargestellt. Kunden und Aufträge werden mithilfe des Association-Elements mit dem Namen Order_Customer
in Beziehung gesetzt.
Jede Entität in der Zuordnung wird als End bezeichnet. In dieser Zuordnung kann das End, das einen Kunden darstellt, mit vielen Aufträgen verbunden sein. Das End, das Aufträge darstellt, kann jedoch nur einem Kunden zugeordnet sein. In der Schemasyntax wird dies mithilfe des Multiplicity-Attributs definiert. Das End dieser Zuordnung mit dem Namen Customers
verfügt über eine Multiplicity="1"
und das End mit dem Namen Orders
über eine Multiplicity="*"
. Dies ist ein Beispiel für eine 1:n-Zuordnung. Weitere Informationen zu den Zuordnungstypen finden Sie unter Zuordnung (EDM).
Nach der Definition der Order_Customer
-Zuordnung mithilfe des Association-Schemaelements wird die Zuordnung zusammen mit den in diesem Beispiel verwendeten Entitäten als AssociationSet in einen EntityContainer eingefügt. Weitere Informationen zu Zuordnungssätzen und Entitätencontainern finden Sie unter EntityContainer-Element (CSDL).
Im folgenden Schemabeispiel werden Entitäten, die Customers
, Orders
und OrderLines
darstellen, sowie zwei Zuordnungen definiert: Order_Customer
und OrderLine_Order
.
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="OrderInfoModel" Alias="Self"
xmlns="https://schemas.microsoft.com/ado/2006/04/edm">
<EntityContainer Name="OrderInfoEntities">
<EntitySet Name="Customers"
EntityType="OrderInfoModel.Customers" />
<EntitySet Name="OrderLines"
EntityType="OrderInfoModel.OrderLines" />
<EntitySet Name="Orders"
EntityType="OrderInfoModel.Orders" />
<AssociationSet Name="Order_Customer"
Association="OrderInfoModel.Order_Customer">
<End Role="Customers" EntitySet="Customers" />
<End Role="Orders" EntitySet="Orders" />
</AssociationSet>
<AssociationSet Name="OrderLine_Order"
Association="OrderInfoModel.OrderLine_Order">
<End Role="Orders" EntitySet="Orders" />
<End Role="OrderLines" EntitySet="OrderLines" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Customers">
<Key>
<PropertyRef Name="CustomerId" />
</Key>
<Property Name="CustomerId" Type="Guid" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false"
MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="Address" Type="String" Nullable="false"
MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="City" Type="String" Nullable="false"
MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="Phone" Type="String" Nullable="false"
MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="ZipCode" Type="Int32" Nullable="false" />
<NavigationProperty Name="Orders"
Relationship="OrderInfoModel.Order_Customer"
FromRole="Customers" ToRole="Orders" />
</EntityType>
<EntityType Name="OrderLines">
<Key>
<PropertyRef Name="OrderLineId" />
</Key>
<Property Name="OrderLineId" Type="Guid" Nullable="false" />
<Property Name="ProductName" Type="String" Nullable="false"
MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="Quantity" Type="Int32" Nullable="false" />
<Property Name="UnitPrice" Type="Decimal" Nullable="false"
Precision="19" Scale="4" />
<Property Name="ExtendedPrice" Type="Decimal"
Nullable="false" Precision="19" Scale="4" />
<NavigationProperty Name="Orders"
Relationship="OrderInfoModel.OrderLine_Order"
FromRole="OrderLines" ToRole="Orders" />
</EntityType>
<EntityType Name="Orders">
<Key>
<PropertyRef Name="OrderId" />
</Key>
<Property Name="OrderId" Type="String" Nullable="false"
MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="TotalAmount"
Type="Decimal" Precision="19" Scale="4" />
<Property Name="Tax" Type="Decimal"
Precision="19" Scale="4" />
<Property Name="ShippingAddress" Type="String"
MaxLength="50" Unicode="true" FixedLength="false" />
<NavigationProperty Name="Customers"
Relationship="OrderInfoModel.Order_Customer"
FromRole="Orders" ToRole="Customers" />
<NavigationProperty Name="OrderLines"
Relationship="OrderInfoModel.OrderLine_Order"
FromRole="Orders" ToRole="OrderLines" />
</EntityType>
<Association Name="Order_Customer">
<End Role="Customers"
Type="OrderInfoModel.Customers" Multiplicity="1" />
<End Role="Orders"
Type="OrderInfoModel.Orders" Multiplicity="*" />
</Association>
<Association Name="OrderLine_Order">
<End Role="Orders"
Type="OrderInfoModel.Orders" Multiplicity="1" />
<End Role="OrderLines"
Type="OrderInfoModel.OrderLines" Multiplicity="*" />
</Association>
</Schema>
Die Order_Customer
-Zuordnung, eine NavigationProperty, wurde für die Customers
-Entität implementiert, um die einfache Navigation und Initialisierung der Zuordnung zu ermöglichen. Die Orders
-Entität verfügt auch über eine NavigationProperty, mit der die darin enthaltenen OrderLines
initialisiert und navigiert werden können. Weitere Informationen zur NavigationProperty-Definition finden Sie unter Navigationseigenschaften (EDM).
Zuordnungs-Mapping und Metadaten
Das Zuweisen der Customers
und Orders
bei 1:n-Zuordnungen wie der Order_Customer
-Zuordnung wird in diesem Beispiel ausgeführt, indem die Zuordnung einer Fremdschlüsselbeziehung zwischen den Tabellen Orders
und Customers
in einer Datenbank zugewiesen wird. Bei dieser Methode sind mehrere Instanzen des Customers
-Fremdschlüssels in der Orders
-Tabelle enthalten, um die den einzelnen Kunden zugeordneten Aufträge darzustellen.
Speicherschema
Beim folgenden Datenspeicherschema-Definitionssprache (SSDL)-Schema handelt es sich um die Speichermetadaten zur Darstellung der Tabellen Customers
, Orders
und OrderLines
. Das SSDL-Schema deklariert diese Tabellen mithilfe von EntityType-Elementen, die den Tabellen in der Datenbank entsprechen. Die Eigenschaften der Entitäten sind den Datentypen des Datenbankmanagementsystems entsprechend typisiert. Beispielsweise ist die Name-Eigenschaft der Customers
-Entität als nvarchar typisiert und nicht als der im CSDL-Schema verwendete String-Typ.
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="OrderInfoModel.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="OrderInfoModelStoreContainer">
<EntitySet Name="Customers"
EntityType="OrderInfoModel.Store.Customers"
store:Type="Tables" Schema="dbo" />
<EntitySet Name="OrderLines"
EntityType="OrderInfoModel.Store.OrderLines"
store:Type="Tables" Schema="dbo" />
<EntitySet Name="Orders"
EntityType="OrderInfoModel.Store.Orders"
store:Type="Tables" Schema="dbo" />
<AssociationSet Name="Order_Customer"
Association="OrderInfoModel.Store.Order_Customer">
<End Role="Customers" EntitySet="Customers" />
<End Role="Orders" EntitySet="Orders" />
</AssociationSet>
<AssociationSet Name="OrderLine_Order"
Association="OrderInfoModel.Store.OrderLine_Order">
<End Role="Orders" EntitySet="Orders" />
<End Role="OrderLines" EntitySet="OrderLines" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Customers">
<Key>
<PropertyRef Name="CustomerId" />
</Key>
<Property Name="CustomerId"
Type="uniqueidentifier" Nullable="false" />
<Property Name="Name"
Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Address"
Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="City"
Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Phone"
Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="ZipCode"
Type="int" Nullable="false" />
</EntityType>
<EntityType Name="OrderLines">
<Key>
<PropertyRef Name="OrderLineId" />
</Key>
<Property Name="OrderLineId"
Type="uniqueidentifier" Nullable="false" />
<Property Name="OrderId"
Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="ProductName"
Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Quantity" Type="int" Nullable="false" />
<Property Name="UnitPrice"
Type="money" Nullable="false" />
<Property Name="ExtendedPrice"
Type="money" Nullable="false" />
</EntityType>
<EntityType Name="Orders">
<Key>
<PropertyRef Name="OrderId" />
</Key>
<Property Name="OrderId"
Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Customer"
Type="uniqueidentifier" Nullable="false" />
<Property Name="TotalAmount" Type="money" />
<Property Name="Tax"
Type="money" />
<Property Name="ShippingAddress"
Type="nvarchar" MaxLength="50" />
</EntityType>
<Association Name="Order_Customer">
<End Role="Customers"
Type="OrderInfoModel.Store.Customers" Multiplicity="1" />
<End Role="Orders"
Type="OrderInfoModel.Store.Orders" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Customers">
<PropertyRef Name="CustomerId" />
</Principal>
<Dependent Role="Orders">
<PropertyRef Name="Customer" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="OrderLine_Order">
<End Role="Orders"
Type="OrderInfoModel.Store.Orders" Multiplicity="1" />
<End Role="OrderLines"
Type="OrderInfoModel.Store.OrderLines" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Orders">
<PropertyRef Name="OrderId" />
</Principal>
<Dependent Role="OrderLines">
<PropertyRef Name="OrderId" />
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
Dieses in SSDL geschriebene Speicherschema legt Datentypen für die Entitäten Customers
und Orders
fest, wenn diese in der Datenbank implementiert werden. Schlüssel-Eigenschaften mit Type="Guid"
im CSDL-Schema haben in der Datenbank den Type="uniqueidentifier"
und müssen mithilfe von Datenbanktypen im Speicherschema angegeben werden.
Eigenschaften, die in CSDL String-Typen sind, werden im Speicher nvarchar-Typen zugeordnet.
Die Zuordnungsspezifikationen sind im Speicherschema und im CSDL-Schema identisch. Wie im CSDL-Schema werden End-Elemente von Zuordnungen mit den Attributen Role, Type und Multiplicity deklariert. Die Zuweisungen End und Role sind dieselben wie in CSDL.
Das ReferentialConstraint-Attribut gibt an, dass die Zuordnungen von den Datenbankstrukturen abhängig sind. Der ReferentialConstraint gibt eine Principle Role sowie Dependent Role- und PropertyRef-Elemente an. Die PropertyRef-Attribute geben die Eigenschaften der End-Entitäten an, die die Primärschlüssel- und Fremdschlüsselspalten der Datenbanktabellen darstellen, welche den Entitäten in der Association entsprechen. Das PropertyRef-Attribut der Principle Role gibt die Spalte an, die den Primärschlüssel enthält. Beispielsweise ist in der Order_Customer
-Zuordnung der PropertyRef der Principle Role die Eigenschaft CustomerId
. Diese Eigenschaft im SSDL-Schema stellt die CustomerId
-Spalte der Customers
-Tabelle dar, die der Fremdschlüsselspalte Customer
in der Orders
-Tabelle zugewiesen wird. Der Fremdschlüssel wird durch den PropertyRef der Dependent Role dargestellt.
Mapping-Spezifikation
Das Zuordnungs-Mapping ähnelt dem Mapping von Entitäten.
Das folgende Mapping-Spezifikationssprache (MSL)-Segment zeigt die AssociationSetMapping mit dem Namen Order_Customer
. Die im CSDL-Schema angegebene OrderInfoModel.Order_Customer
-Zuordnung wird in diesem Beispiel der Orders
-Tabelle im SSDL-Schema zugewiesen, die die Datenbank darstellt.
Mit der PropertyRef auf der Customers
-Seite der Zuordnung wird die CustomerId
-Eigenschaft der Customers
-Entität explizit der Customer
-Spalte in der Orders
-Tabelle zugeordnet. Diese Spalte enthält den Fremdschlüssel, der die Beziehung zwischen den Tabellen Orders
und Customers
in der Datenbank darstellt.
Im folgenden Beispiel ist das vollständige MSL-Schema dargestellt, dem das vorherige Segment entnommen wurde. Dieses Mapping enthält die beiden für dieses Beispiel erforderlichen EntitySetMapping- und AssociationSetMapping-Elemente.
<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S"
xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
<EntityContainerMapping
StorageEntityContainer="OrderInfoModelStoreContainer"
CdmEntityContainer="OrderInfoEntities">
<EntitySetMapping Name="Customers">
<EntityTypeMapping
TypeName="IsTypeOf(OrderInfoModel.Customers)">
<MappingFragment StoreEntitySet="Customers">
<ScalarProperty Name="CustomerId"
ColumnName="CustomerId" />
<ScalarProperty Name="Name" ColumnName="Name" />
<ScalarProperty Name="Address" ColumnName="Address" />
<ScalarProperty Name="City" ColumnName="City" />
<ScalarProperty Name="Phone" ColumnName="Phone" />
<ScalarProperty Name="ZipCode" ColumnName="ZipCode" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="OrderLines">
<EntityTypeMapping
TypeName="IsTypeOf(OrderInfoModel.OrderLines)">
<MappingFragment StoreEntitySet="OrderLines">
<ScalarProperty Name="OrderLineId"
ColumnName="OrderLineId" />
<ScalarProperty Name="ProductName"
ColumnName="ProductName" />
<ScalarProperty Name="Quantity"
ColumnName="Quantity" />
<ScalarProperty Name="UnitPrice"
ColumnName="UnitPrice" />
<ScalarProperty Name="ExtendedPrice"
ColumnName="ExtendedPrice" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="Orders">
<EntityTypeMapping
TypeName="IsTypeOf(OrderInfoModel.Orders)">
<MappingFragment StoreEntitySet="Orders">
<ScalarProperty Name="OrderId" ColumnName="OrderId" />
<ScalarProperty Name="TotalAmount"
ColumnName="TotalAmount" />
<ScalarProperty Name="Tax" ColumnName="Tax" />
<ScalarProperty Name="ShippingAddress"
ColumnName="ShippingAddress" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<AssociationSetMapping Name="Order_Customer"
TypeName="OrderInfoModel.Order_Customer"
StoreEntitySet="Orders">
<EndProperty Name="Customers">
<ScalarProperty Name="CustomerId"
ColumnName="Customer" />
</EndProperty>
<EndProperty Name="Orders">
<ScalarProperty Name="OrderId" ColumnName="OrderId" />
</EndProperty>
</AssociationSetMapping>
<AssociationSetMapping Name="OrderLine_Order"
TypeName="OrderInfoModel.OrderLine_Order"
StoreEntitySet="OrderLines">
<EndProperty Name="Orders">
<ScalarProperty Name="OrderId"
ColumnName="OrderId" />
</EndProperty>
<EndProperty Name="OrderLines">
<ScalarProperty Name="OrderLineId"
ColumnName="OrderLineId" />
</EndProperty>
</AssociationSetMapping>
</EntityContainerMapping>
</Mapping>
Die in diesem Thema dargestellten Codesegmente enthalten die vollständigen Schemas für das Erstellen eines Programmierobjektmodells im OrderInfo
-Namespace und dessen Zuordnung zum Speicher. Ein Beispiel für Code, in dem dieses Modell verwendet wird, finden Sie unter Anwendungscode mit Zuordnungen (EDM).
Partielle Klassenmethoden
Im EDM können Hilfsmethoden in partiellen Klassen implementiert werden, um die Funktionalität von Anwendungen zu verbessern. Im folgenden Beispiel wird eine Hilfsmethode der Orders
-Klasse dargestellt. Diese Hilfsmethode summiert die ExtendedPrice
-Beträge der OrderLines
eines Auftrags, um die TotalAmount
einer Order
zu berechnen. Weitere Informationen finden Sie unter Hilfsmethoden (EDM).
using System;
using System.Data;
namespace OrderInfoModel
{
public partial class Orders :
global::System.Data.Objects.DataClasses.EntityObject
{
public decimal ComputeOrder()
{
this.TotalAmount = 0;
foreach (OrderLines orderLine in this.OrderLines)
{
orderLine.ExtendedPrice =
orderLine.Quantity * orderLine.UnitPrice;
this.TotalAmount = this.TotalAmount +
orderLine.ExtendedPrice;
}
this.Tax = Decimal.Round(((decimal)this.TotalAmount *
(decimal) .08), 2);
this.TotalAmount = this.TotalAmount + this.Tax;
return (decimal)this.TotalAmount;
}
}
}
Implementieren der Datenbank
Das folgende Skript kann zum Erstellen der Datenbank für dieses Beispiel verwendet werden. So erstellen Sie die OrderInfo-Datenbank mit SQL Server Management Studio:
Zeigen Sie im Menü Datei auf Neu, und klicken Sie dann auf Datenbankmodul-Abfrage.
Geben Sie im Dialogfeld Verbindung mit Datenbankmodul herstellen entweder localhost oder den Namen der SQL Server-Instanz ein, und klicken Sie anschließend auf Verbinden.
Fügen Sie das folgende Transact SQL-Skript im Abfragefenster ein, und klicken Sie dann auf Ausführen.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
USE [master]
GO
IF EXISTS (SELECT * FROM sys.databases
WHERE name = 'OrderInfo')
DROP DATABASE OrderInfo;
GO
-- Create the database.
CREATE DATABASE OrderInfo;
GO
USE OrderInfo;
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Customers]') AND type in (N'U'))
BEGIN
CREATE TABLE [Customers](
[CustomerId] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Address] [nvarchar](50) NOT NULL,
[City] [nvarchar](50) NOT NULL,
[Phone] [nvarchar](50) NOT NULL,
[ZipCode] [int] NOT NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED
(
[CustomerId] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) 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'[Orders]') AND type in (N'U'))
BEGIN
CREATE TABLE [Orders](
[OrderId] [nvarchar](50) NOT NULL,
[Customer] [uniqueidentifier] NOT NULL,
[TotalAmount] [money] NULL,
[Tax] [money] NULL,
[ShippingAddress] [nvarchar](50) NULL,
CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED
(
[OrderId] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) 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'[OrderLines]') AND type in (N'U'))
BEGIN
CREATE TABLE [OrderLines](
[OrderLineId] [uniqueidentifier] NOT NULL,
[OrderId] [nvarchar](50) NOT NULL,
[ProductName] [nvarchar](50) NOT NULL,
[Quantity] [int] NOT NULL,
[UnitPrice] [money] NOT NULL,
[ExtendedPrice] [money] NOT NULL,
CONSTRAINT [PK_OrderLines] PRIMARY KEY CLUSTERED
(
[OrderLineId] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[Order_Customer]') AND parent_object_id = OBJECT_ID(N'[Orders]'))
ALTER TABLE [Orders] WITH CHECK ADD CONSTRAINT [Order_Customer] FOREIGN KEY([Customer])
REFERENCES [Customers] ([CustomerId])
GO
ALTER TABLE [Orders] CHECK CONSTRAINT [Order_Customer]
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[OrderLine_Order]') AND parent_object_id = OBJECT_ID(N'[OrderLines]'))
ALTER TABLE [OrderLines] WITH CHECK ADD CONSTRAINT [OrderLine_Order] FOREIGN KEY([OrderId])
REFERENCES [Orders] ([OrderId])
GO
ALTER TABLE [OrderLines] CHECK CONSTRAINT [OrderLine_Order]
Siehe auch
Konzepte
Zuordnung (EDM)
Navigationseigenschaften (EDM)
Implementieren von Entitäten (EDM)
Weitere Ressourcen
Schemas und Mappingspezifikation (Entity Framework)
Beispielanwendungen (Entity Framework)