Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

EDM : comment contourner les problématiques liées aux bases inadéquates

Durant la formation que j'anime cette semaine, un de mes stagiaires a essayé de me coller en me donnant une base pour laquelle l'utilisation d'EF n'était, soit disant, pas possible. Heureusement, mon honneur et celui de l'EF est sauf... Smile

En effet, cette base n'est pas idéale pour EF. Elle est composée

  • d'une  table Bases avec 4 colonnes:
    • Id, int, Identity (PK)
    • Key, int, not null
    • Value, int, not null
    • Text, nvarchar

Value est un entier compris entre 1 et 9 qui ne peut plus évoluer une fois qu'il est affecté et Key est égale à  Id * 10 + Value

  • d'une table Inheriteds avec 3 colonnes:
    • Id, int, Indentity (PK)
    • Key, int, not null
    • Text2, nvarchar

Key est la même que dans la table Bases et donc, on a en réalité une relation 1 -> 0..1 entre Bases et Inheriteds même si cette relation n'existe pas en base.

  • d'une table Descriptions avec 4 colonnes:
    • Id, int, Identity (PK)
    • Key, int, not null
    • Language, nchar
    • Text, nvarchar

Key est, là aussi, la même que Bases avec une relation (non présente en base) 1 -> * entre Bases and Descriptions, comme si la PK de Descriptions était composée de Key et de Language.

Côté CSDL (description des entités), il voulait avoir :

  • une classe Base asbtraite (mappée sur Bases)
  • une classe Entity qui hérite de Base (mappée sur Inheriteds)
  • une classe Description
  • une relation 1 -> * entre Base et Description

Est-il possible de réaliser ce scénario avec EF ? Voud l'aurez compris en lisant le débit de ce post, yes we can! Smile

Comment faire cela ?

  • Tout d'abord, dans le designer, après avoir importé les tables and avoir renommer les entity types générées, il fait dupprimer la propriété Id de chacune d'entre elles.
  • Ensuite, il faut définir Base.Key, Description.Key et Description.Language comme des EntityKey.
  • Définir Base comme abstraite 
  • Supprimer Entity.Key
  • Ajouter la relation d'héritage entre Entity et Base et mettre à jour le mapping de Entity (ie: il faut mapper la colonne Key sur la propriété Base.Key)
  • Ajouter la relation entre Base et Description

Bien entendu, quand on en est là, notre EDM n'est pas correcte (rien ne permet de garantir l'intégrité des données ni l'unicité des entity keys).

Pour résoudre cela, il fait changer le SSDL (description de la BD) et simuler une base "idéale" sans Id avec Key comme PK).

Comme Key est calculée, il faut changer son StoreGeneratedPattern et le passé à Computed.

Ensuite, il faut gérer les opérations CUD de la base sur Base car il faut calculer la KeyValue.

Base étant abstraite donc il faut définir les opérations CUD pour ses entity types héritées (Entity dans notre cas).

<EntityContainer Name="TestModelStoreContainer">

    <EntitySet Name="Bases" EntityType="TestModel.Store.Bases" store:Type="Tables" Schema="dbo" />

    <EntitySet Name="Descriptions" EntityType="TestModel.Store.Descriptions" store:Type="Tables" Schema="dbo" />

    <EntitySet Name="Inheriteds" EntityType="TestModel.Store.Inheriteds" store:Type="Tables" Schema="dbo" />

</EntityContainer>

<EntityType Name="Bases">

    <Key>

        <PropertyRef Name="Key" />

    </Key>

    <!--<Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />-->

    <Property Name="Key" Type="int" Nullable="false" StoreGeneratedPattern="Computed" />

    <Property Name="Value" Type="int" Nullable="false" />

    <Property Name="Text" Type="nvarchar" MaxLength="50" />

</EntityType>

<EntityType Name="Descriptions">

    <Key>

        <PropertyRef Name="Key" />

        <PropertyRef Name="Language" />

    </Key>

    <!--<Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />-->

    <Property Name="Key" Type="int" Nullable="false" />

    <Property Name="Language" Type="nchar" Nullable="false" MaxLength="20" />

    <Property Name="Text" Type="nvarchar" MaxLength="50" />

</EntityType>

<EntityType Name="Inheriteds">

    <Key>

        <PropertyRef Name="Key" />

    </Key>

    <!--<Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />-->

    <Property Name="Key" Type="int" Nullable="false" StoreGeneratedPattern="Computed" />

    <Property Name="Text2" Type="nvarchar" MaxLength="50" />

</EntityType>

 

<Function Name="InsertEntity" IsComposable="false">

    <CommandText>

        INSERT INTO Bases

        ([Key], Value ,[Text])

        VALUES

        (-1, @Value, @Text)

 

        DECLARE @IdValue int

        SET @IdValue = SCOPE_IDENTITY()

 

        DECLARE @KeyValue int

        SET @KeyValue = @IdValue * 10 + @Value

 

        UPDATE Bases

        SET [Key] = @KeyValue

        WHERE Id = @IdValue

 

        INSERT INTO Inheriteds

        ([Key], Text2)

        VALUES

        (@KeyValue, @Text2)

 

        SELECT @KeyValue AS KeyValue

    </CommandText>

    <Parameter Name="Value" Type="int" />

    <Parameter Name="Text" Type="nvarchar" MaxLength="50" />

    <Parameter Name="Text2" Type="nvarchar" MaxLength="50" />

</Function>

<Function Name="UpdateEntity" IsComposable="false">

    <CommandText>

        UPDATE Bases

        SET [Text] = @Text

        WHERE [Key] = @Key

 

        UPDATE Inheriteds

        SET Text2 = @Text2

        WHERE [Key] = @Key

    </CommandText>

    <Parameter Name="Key" Type="int" />

    <Parameter Name="Text" Type="nvarchar" MaxLength="50" />

    <Parameter Name="Text2" Type="nvarchar" MaxLength="50" />

</Function>

<Function Name="DeleteEntity" IsComposable="false">

    <CommandText>

        DELETE Inheriteds

        WHERE [Key] = @Key

 

        DELETE Bases

        WHERE [Key] = @Key

    </CommandText>

    <Parameter Name="Key" Type="int" />

</Function>

Maintenant, il ne reste plus qu'à définir le mapping de l'entity type Entity avec  mes SSDL functions:

<EntitySetMapping Name="BaseSet">

    <EntityTypeMapping TypeName="IsTypeOf(TestModel.Base)">

        <MappingFragment StoreEntitySet="Bases">

            <ScalarProperty Name="Key" ColumnName="Key" />

            <ScalarProperty Name="Value" ColumnName="Value" />

            <ScalarProperty Name="Text" ColumnName="Text" />

        </MappingFragment>

    </EntityTypeMapping>

    <EntityTypeMapping TypeName="TestModel.Entity">

        <MappingFragment StoreEntitySet="Inheriteds">

            <ScalarProperty Name="Key" ColumnName="Key" />

            <ScalarProperty Name="Text2" ColumnName="Text2" />

        </MappingFragment>

        <ModificationFunctionMapping>

            <InsertFunction FunctionName="TestModel.Store.InsertEntity">

                <ScalarProperty Name="Value" ParameterName="Value"/>

                <ScalarProperty Name="Text" ParameterName="Text"/>

                <ScalarProperty Name="Text2" ParameterName="Text2"/>

                <ResultBinding Name="Key" ColumnName="KeyValue"/>

            </InsertFunction>

            <UpdateFunction FunctionName="TestModel.Store.UpdateEntity">

                <ScalarProperty Name="Key" ParameterName="Key" Version="Current"/>

                <ScalarProperty Name="Text" ParameterName="Text" Version="Current"/>

                <ScalarProperty Name="Text2" ParameterName="Text2" Version="Current"/>

            </UpdateFunction>

            <DeleteFunction FunctionName="TestModel.Store.DeleteEntity">

                <ScalarProperty Name="Key" ParameterName="Key"/>

            </DeleteFunction>

        </ModificationFunctionMapping>

    </EntityTypeMapping>

</EntitySetMapping>

Mon modèle est maintenant valide. Je peux avoir une bonne conception de mes entités sans me soucier des contraintes de la base.

Alors, c'est pas trop fort EF ? Moi je dis : franchement, EF, c'est trop la classe ! Smile

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Publié jeudi 29 janvier 2009 16:28 par Matthieu MEZIL

Commentaires

# re: EDM : comment contourner les problématiques liées aux bases inadéquates @ jeudi 29 janvier 2009 17:13

Merci Matthieu pour tes billets ...

Tu m'as fait plonger dans ED ... j'ai galéré au début car la base que je devais taper était tout sauf idéale ... et avec tes billets qui m'ont mis sur des pistes ... j'ai toujours réussi à obtenir ce que je voulais.

Certes, je suis persuadé que c'est loin d'être idéal et optimal ... mais ca me permet de savoir que ED a de la ressource :p

Erebuss

# re: EDM : comment contourner les problématiques liées aux bases inadéquates @ vendredi 30 janvier 2009 09:52

Merci :-)

Par contre pourquoi ED (tu travailles dans le hard discount Smile) ? soit EF soit EDM mais pas ED !

Matthieu MEZIL

# re: EDM : comment contourner les problématiques liées aux bases inadéquates @ vendredi 30 janvier 2009 09:59

LoL

C'est à cause du projet sur lequel je bosse ... il y a une partie qui est surnommée ED ...

Vivement le Weekend lol

Erebuss

# re: EDM : comment contourner les problématiques liées aux bases inadéquates @ mardi 3 février 2009 15:57

Bonjour Matthieu.

C'est vrai que c'est magnifique (c'est moi qui avait le modèle de données qui collait pas avec EF).

J'ai encore pas mal d'interrogations sur l'EF (le contraire serait étonnant vu l'étendue de l'outil...), c'était bien Julia Lerman que tu nous avais conseillé (j'ai vu qu'elle avait un bouquin sur l'EF chez O'Reilly) ?

Merci

Alexis

acoudeyras

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- [SharePoint] Les sessions TechDays 2012… par Le blog de Patrick [MVP SharePoint] le il y a 6 heures et 45 minutes

- TechDays Paris 2012 : Session pleinière jour 3 par Blog Technique de Romelard Fabrice le 02-09-2012, 11:01

- Mishra Reader : un lecteur RSS très Zune Style en Open Source ! par Cyril Sansus le 02-09-2012, 08:28

- [framework 4] Les Tasks et le Thread UI par Fathi Bellahcene le 02-09-2012, 00:33

- Workflow Foundation 3 a un pied dans la tombe par Blog de Jérémy Jeanson le 02-08-2012, 22:15

- TechDays Paris 2012 : Nouvelles tendances du poste de travail - Bring Your own PC par Blog Technique de Romelard Fabrice le 02-08-2012, 19:42

- TechDays Paris 2012 : System Center Service Manager 2012 Vue d’ensemble par Blog Technique de Romelard Fabrice le 02-08-2012, 17:32

- TechDays Paris 2012 : Pleinière second jour par Blog Technique de Romelard Fabrice le 02-08-2012, 16:23

- TechDays Paris 2012 : Retour d'expérience sur la mise en place d'un Cloud Privé par Blog Technique de Romelard Fabrice le 02-08-2012, 16:04

- TechDays Paris 2012 : Comment SharePoint a sauvé mes TechDays par Blog Technique de Romelard Fabrice le 02-07-2012, 23:59