Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework

Suite à la pertinente remarque de Simon, j’ai modifié le code ci-dessous par rapport à la version originale.

Les démos WCF RIA Services utilisent quasiment toutes Entity Framework Sourire mais en l’utilisant de façon ultra basique et donc pas toujours de façon optimale. Triste Je pense que ça peut se comprendre puisque l’idée est de faire une démo de WCF RIA Services mais que ça a un côté dangereux car, sortie de l’aspect démo, les utilisateurs de la “vraie vie” vont souvent l’utiliser de la même façon.

Comme je l’avais expliqué dans ce post, la méthode Include est sympa mais pourrie en perf dans sa version actuelle.

Avec WCF RIA Services, il est possible d’utiliser l’attribut Include sur les metadatas pour récupérer les entités liées en même temps que l’entité qu’on requête.

Je vous invite à regarder le post d’Audrey sur le sujet pour en savoir plus.

Maintenant côté code, la manière basique de la démo serait d’écrire ceci :

public IQueryable<Customer> GetCustomers()
{
    return this.ObjectContext.Customers;
}

public IQueryable<Customer> GetCustomersWithOrders()
{
    return this.ObjectContext.Customers.Include("Orders");
}

Cependant, il est beaucoup plus performant d’écrire ceci de charger les orders séparément :

public IQueryable<Customer> GetCustomers()
{
    return this.ObjectContext.Customers;
}

public IQueryable<Customer> GetCustomersWithOrders()
{
    return this.ObjectContext.Customers;
}

Du coup, je surcharge la méthode Query :

public override IEnumerable Query(QueryDescription queryDescription, out IEnumerable<ValidationResult> validationErrors, out int totalCount)
{
    var value = base.Query(queryDescription, out validationErrors, out totalCount);
    if (queryDescription.Method.Name == ReflectionUtil.GetMethodName(() => GetCustomersWithOrders()))
    {
        IEnumerable<string> customerIds = value.Cast<Customer>().Select(c => c.CustomerID);
        foreach (var order in ObjectContext.Orders.Where(o => customerIds.Contains(o.CustomerID))) ;
    }
    return value;
}

avec le code suivant pour ma classe ReflectionUtil:

public static class ReflectionUtil
{
    public static string GetMethodName(Expression<Action> action)
    {
        MethodCallExpression methodCallexpression = action.Body as MethodCallExpression;
        if (methodCallexpression != null)
            return methodCallexpression.Method.Name;
        return null;
    }
}
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é mardi 16 novembre 2010 11:31 par Matthieu MEZIL

Commentaires

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ mardi 16 novembre 2010 15:37

Et si on a juste une association unidirectionnelle de Customer vers Orders. Ca marche aussi ?

tja

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ mardi 16 novembre 2010 15:43

Merci, c'est bien intéressant ce post !

jmix90

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ mardi 16 novembre 2010 16:26

@Thomas : dans le sens Customer vers Orders c'est également valable oui.

En fait, l'idée de l'Include c'est que pour tout te remonter d'un coup, EF fait un LEFT OUTER JOIN mais qui implique une requête plus lente, avec une bonne partie des données dupliquées + une matérialization en entité plus lente.

Du coup il vaut mieux faire deux requêtes sauf si t'es dans du quasi 1 pour 1.

Matthieu MEZIL

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ mardi 16 novembre 2010 16:37

Merci, c'est très clair :)

tja

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ mardi 16 novembre 2010 16:58

Hmm... imaginons que ta base contient 1000 customers, avec en moyenne 10 orders chacun. Le client accede au customer par pages de 20

=&gt; A chaque fois que tu charge une page de customer tu charges l'integralite de tes orders, c'est tout bad.

Il faut pas oublier que ce que les requetes que tu exposes dans ton Domain Service peuvent etre recomposees (filtrees, triees, paginees) et ton optim vaut pour une base a faible volumetrie, mais pour une vrai base de prod avec un peu d'historique, c'est la cata !

(Par contre si tu peux me trouver un truc elegant qui tient compte de cette remarque, je prends !)

simon ferquel

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ mardi 16 novembre 2010 18:08

Mais quel boulet je fais !

Merci Simon

Voilà c'est corrigé.

Matthieu MEZIL

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ mercredi 17 novembre 2010 11:05

Bonjour Matthieu,

Voici ce qu'on écrit pour faire la même chose avec notre DAL.

dm.LoadAssociated

<Orders, CustomerOrders="">();

C'est moins fun à écrire (quand on aime écrire du code compliqué), mais plus efficace.

Ah oui, et on peut filtrer, trier, paginer, et ajouter autant d'étages qu'on veut dans le graphe, et ca marche tout pareil avec les relations N-N ...

Voilà, c'était la minute de pub pour Aspectize.

A bientôt !

nicolas roux

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ jeudi 18 novembre 2010 00:51

@ Nicolas : pour info je ne suis pas fan de WCF RIA Services (du moins en l'état).

"on peut filtrer, trier, paginer, et ajouter autant d'étages qu'on veut dans le graphe, et ca marche tout pareil avec les relations N-N ..."

Avec ma solution N-Tiers basées sur T4, je peux aussi faire tout cela.

Si on est pas sur du 2 tiers, EF sait bien sûr le faire tout seul.

Par pure curiosité, peux-tu m'en dire plus sur "dm.LoadAssociated

<Orders, CustomerOrders="">();" stp? Imaginons que mon client (au sens 3 tiers) veuille récupérer du 21ème au 30ème customers triés par CompanyName avec leur dernier Order. Tu fais comment avec votre solution ?

Matthieu MEZIL

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ jeudi 18 novembre 2010 12:57

Bonjour Matthieu,

Je préviens, je suis débutant en RIA Services.

Je tente de charger le contenu d'une table et de quelques unes des tables liées.

J'ai tenté d'effectuer le traitement avec la méthode Include mais une exception est levée (utilisation d'une commande OUTER APPLY).

Je tente donc de faire un chargement "manuel" suivant ce que tu proposes mais les entités ne sont pas liées entre elles.

Ex :

System.Data.Objects.ObjectQuery

<contact> requete_contacts = this.ObjectContext.contacts; }

// Création de la requête de récupération des types

IEnumerable<int?> echotypes_id_from_contacts = requete_contacts.Cast<contact>().Select(c =&gt; c.idechotype);

System.Data.Objects.ObjectQuery<echotype> echotypes_from_contacts = (System.Data.Objects.ObjectQuery<echotype>)this.ObjectContext.echotypes.Where(o =&gt; echotypes_id_from_contacts.Contains(o.idechotype));

// Création de la requête de récupération des catégories

IEnumerable<int> echocategories_id_from_contacts = echotypes_from_contacts.Cast<echotype>().Select(c =&gt; c.idechocategory);

System.Data.Objects.ObjectQuery<echocategory> echocategories_from_contacts = (System.Data.Objects.ObjectQuery<echocategory>)this.ObjectContext.echocategories.Where(o =&gt; echocategories_id_from_contacts.Contains(o.idechocategory));

// Récupération des données

//foreach (var o in echocategories_from_contacts) ;

//foreach (var o in echotypes_from_contacts) ;

echocategories_from_contacts.ToList();

echotypes_from_contacts.ToList();

// requete_contacts.ToList(); // fonctionne

return requete_contacts;

Donc, côté client, si je commente "requete_contacts.ToList();" alors mes entités ne pointent pas sur les catégories.

Si je décommente, mes entités sont magnifiquement liées.

Est-ce normal ?

Il me semble qu'il serait incorrect d'effectuer cette requête côté serveur mais y a-t'il une autre solution ?

Merci d'avance pour vos avis sur cette question de noob ...

@+

Benoit Andrieu

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ jeudi 18 novembre 2010 15:56

Bon, il semblerait que j'ai dit de la merde.

Le débogueur me montre parfois les valeurs à "null" côté client mais elles sont bien affichées dans l'interface...

Merci...

Benoit Andrieu

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ jeudi 18 novembre 2010 23:15

@Benoit: de rien :p

Matthieu MEZIL

# re: WCF RIA Services ne doit pas vous faire oublier les bonnes pratiques d’Entity Framework @ vendredi 19 novembre 2010 12:35

Bon, en fait, je suis un gros boulet ! ^^

J'avais rajouté (et oublié que j'avais rajouté) un chargement de toutes les entités côté client :

EntityQuery

<echotype> requete_b = m_domainContext.GetEchotypesQuery();

m_domainContext.Load(requete_b, OnEchotypesLoaded, null);

Donc, en fait, ça ne marche pas ! ^^

Si je fais le chargement côté serveur alors le contexte du client n'est pas mis à jour.

Une idée ? ^^

Je sens que je vais y passer ma journée... -_-'

Encore... -_-'''

Benoit Andrieu

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01