Wednesday, January 02, 2008

Mehrere Tabellen auf eine Entität mappen

Meistens sind Daten in einer Datenbank normalisiert abgelegt. In der Applikation möchte man aber oft mit den nicht normalisierten Daten arbeiten. Ist das ADO.NET Entity Framework die Lösung?

Jein lautet die Antwort. Und um es vorne weg zu nehmen, ein Mapping von mehreren Tabellen auf eine Entität ist möglich, aber nur wenn diese eine 1:1 Beziehung haben. Das heisst, in den meisten Fällen wird man besser fahren, wenn auf der Datenbank eine geeignete View erstellt, diese auf die Entität gemapped und das Update, Insert und Delete über Stored Procedures gelöst wird.

Nun aber zur Lösung. Zuerst wird ein Model mit dem Assistenten erstellt, das alle gewünschten Tabellen enthält.

Die Anpassungen am Conceptual Model (CSDL) sind einfach. Auf der Entität werden die gewünschten Attribute aus den weiteren Tabellen hinzugefügt. So wurde etwa hier die Entität Cars um das Attribut Value erweitert.

<?xml:namespace prefix = edmx /><edmx:conceptualmodels>
<schema xmlns="http://schemas.microsoft.com/ado/2006/04/edm" alias="Self" namespace="Model">
<entitycontainer name="Entities">
<entityset name="Cars" entitytype="Model2.Cars">
</entitycontainer>
<entitytype name="Cars">
<key>
<propertyref name="ID_Cars">
</key>
<property name="ID_Cars" nullable="false" type="Guid"></property>
<property name="Brand" type="String" maxlength="50"></property>
<property name="Model" type="String" maxlength="50"></property>
<property name="Value" type="String" maxlength="50"></property>
</entitytype>
</schema>
</edmx:conceptualmodels>

Anpassungen am Storage Model (SSDL) sind keine notwendig, da sich an der Datenbank, welche durch dieses Model repräsentiert wird, nichts ändert.

Durch Anpassung des Mappings werden die neu definierten Attribute auf der Entität nun auf die im Storage Model vorhandenen gemapped. Dies wird realisiert durch Hinzufügen eines zusätzlichen Mapping Fragment.

<edmx:mappings>
<mapping xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS" space="C-S">
<entitycontainermapping cdmentitycontainer="Entities" storageentitycontainer="dbo">
<entitysetmapping name="Cars">
<entitytypemapping typename="IsTypeOf(Model.Cars)">
<mappingfragment storeentityset="Cars">
<scalarproperty name="ID_Cars" columnname="ID_Cars">
<scalarproperty name="Brand" columnname="Brand">
<scalarproperty name="Model" columnname="Model">
</mappingfragment>
<mappingfragment storeentityset="Extensions">
<scalarproperty name="ID_Cars" columnname="ID_Extensions">
<scalarproperty name="Value" columnname="Value">
</mappingfragment>

</entitytypemapping>
</entitysetmapping>
</entitycontainermapping>
</mapping>
</edmx:mappings>

Nicht mehr benötigter Code wie EntitySets und AssociationSets sind im CSDL und dem Mapping zu löschen.