EF6 : Tips&Tricks

EF Core va bientôt prendre la relève mais je pense que EF6 va continué son chemin pendant encore un bon bout de temps avant de disparaître ! C’est pourquoi je me suis dit que j’allais partager avec vous toutes les petites astuces que j’ai découvert ces dernières années.

I. Performances

1) READ_COMMITTED_SNAPSHOT

C’est un paramètre SQL Server au niveau de la base de donnée qui est mis de base en code first, et qui permet « potentiellement » une meilleur scalabilité et moins de deadlocks.

En gros, ça crée un snapshot de la base en read-only sur lequel les SELECT seront executé. Quand un changement s’effectue (par ex : un UPDATE) il s’effectue sur la base (et non sur le snapshot) et un nouveau snapshot de la base est créé.

Ce paramètre est particulièrement adapté lorsque la majorité des requêtes effectuées sont des SELECT.

Commande :

ALTER DATABASE <dbname> SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE <dbname> SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE <dbname> SET MULTI_USER;

2) Warm-up

Lors de la 1ère requête à un Model, EF fait beaucoup de choses avant de pouvoir l’exécuter, cela peut facilement prendre 5-6sec !

Afin d’éviter cela vous pouvez améliorer les choses à plusieurs niveaux, mais personnellement j’ai choisi de contourner le problème en maintenant à chaud mon site sous IIS. Voir cet article de blog pour plus d’infos.

Vous pouvez aussi décider d’utiliser NGEN qui permet d’éviter que l’assembly d’EF (qui est grosse, environ 5Mo) soit JIT à chaque lancement. On peut gagner environ 1-3secondes.

Vous pouvez aussi consulter cet article MSDN pour en savoir plus ce qui se passe et les différentes pistes d’amélioration possibles.

3) Les méthodes async

Sur un site web ou une Web Api le nombre de thread est limité et l’utilisation des méthodes Async de EF permet de libérer le thread courant afin qu’il commence le traitement d’une requête le temps que la base de donnée retourne le résultat.

Plus d’infos sur cet article de blog ou cet article msdn.

4) NoTracking

Lorsque vous faites une requête avec EF, l’état de l’objet est ensuite tracké par le contexte. Régulièrement on n’a pas besoin de ce tracking et cela entraine juste une hausse des consommations CPU/RAM et une perte de performance, surtout dans le cadre de recherche où le nombre d’items retournés est élevé !

Pour éviter de tracker, rien de plus simple, il suffit de rajouter AsNoTracking() à la fin de la query !

Exemple :

var blogs2 = context.Blogs
 .Where(b => b.Name.Contains(".NET"))
 .AsNoTracking()
 .ToList();

5) NCache

NCache est passé OpenSource et peut servir de cache de 2nd niveau pour EF.

6) Break queries

Afin d’améliorer les performances il est souvent préférable de découper une grosse requête en plusieurs petites afin de limiter le nombre d’include.

7) Optimiser les Update via des jointures conditionnelles

Le cas standard d’un update avec EF est le suivant :

L’utilisateur modifie quelques champs -> le client envoie au serveur l’entité entière -> on récupère le graph complet de l’entité côté serveur -> on mappe les champs -> on sauvegarde

Une optimisation courante est donc d’effectuer uniquement les jointures dont on a besoin pour mettre à jour l’entité en base.

La détection du changement peut être faite via le calcul des hashs des entités enfants côté serveur au moment du Get. On recalculera ces mêmes hashs au moment de la sauvegarde et on comparera les hash entre le Get et l’Update pour voir si l’entité enfant doit être mise à jour, et donc si la jointure doit être faite.  Les hashs seront stockés dans une variable au niveau de chaque entité enfants. Pour économiser des cycles CPU serveurs ou de la bande passante ce calcul de hash peut être déporté sur le client.

Exemple

 IQueryable<CLIENT> query = _database.CLIENT; 
 if (clsPersonne.hashIdentiteContactPhysiqueAvant != clsPersonne.hashIdentiteContactPhysiqueApres) 
 query = query.Include(x => x.IDENTITE_CONTACT_PHYSIQUE); 
 ...
 ...
 var client = query.SingleOrDefault(x => x.Id = clsPersonne.Id);

8) Entity Framework Extended Library

Librairie pour EF permettant d’ajouter des fonctionnalités à EF comme les Batch Update/Delete (de base dans EF, on ne peut mettre à jour qu’une ligne par requête).

Permet aussi de gérer un cache simpliste.

9) Au cas où…

N’oublier pas de vérifier vos index et que vos types de données correspondent !

 

2. Les requêtes

1) Mémo pour gérer les graphs d’entités

 

2) Find au lieu de SingleOrDefault

La méthode Find de DbSet permet d’aller récupérer une entité du contexte via sa Primary Key, si l’élément n’est pas trouvé dans le contexte, l’élément est récupéré depuis la base.

Alors qu’avec SingleOrDefault la requête sera toujours exécutée.

3) Logger / Intercepter les requêtes SQL

Une nouveauté peu connue de EF 6.1 est de pouvoir logger les requêtes SQL très facilement, il suffit d’ajouter dans le .config :

<interceptors>
 <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
 <parameters>
 <parameter value="C:\Temp\LogOutput.txt"/>
 <parameter value="false" type="System.Boolean"/>
 </parameters>
 </interceptor>
 </interceptors>
  • Booléen à False : Le fichier est réécrit à chaque fois que l’application redémarre
  • Booléen à True: Le texte est ajouté à la fin du fichier

4) Func<> vs Expression<Func<>>

Si on souhaite réaliser un filtre, par exemple:

Expression<Func<YourEntity, bool>> FilterByNameLength(int length)

{

return x => x.Name.Length > length;

}

On l’utilise de la manière suivante :

context.Table.Where(FilterByNameLength(500));

Si vous passer une Func<> à une query EF (pour appliquer un filtre par exemple), la méthode ne sera pas traduite en SQL et sera appliquée a posteriori ce qui est rarement ce que l’on souhaite.

Alors que si on utile une Expression<Func<>> la méthode sera bien traduite en SQL.

5) eSQL

Entity SQL (eSQL) est un language indépendant du stockage permettant de récupérer des données sous formes d’objets ou de forme tabulaire. Cela peut être très pratique pour créer des requêtes dynamiques.

Exemple :

using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    string esqlQuery = @"SELECT VALUE Contact
        FROM AdventureWorksEntities.Contacts as Contact where Contact.LastName = @ln";

    // The following query returns a collection of Contact objects.
    ObjectQuery<Contact> query = new ObjectQuery<Contact>(esqlQuery, context, MergeOption.NoTracking);
    query.Parameters.Add(new ObjectParameter("ln", "Zhou"));

    // Iterate through the collection of Contact items.
    foreach (Contact result in query)
        Console.WriteLine("Contact First Name: {0}; Last Name: {1}",
                result.FirstName, result.LastName);
}

6) UnitOfWork

C’est un design pattern qui permet d’abstraire toute la couche de persistence tout en évitant de réinstancier le DBContext à chaque opération (ce qui permet aussi de faire des transactions très simplement). Voir cet article msdn pour plus d’informations.

7) DbFunctions

Cette méthode possède des fonctions utilitaires afin d’effectuer des opérations sur les dates au sein des requêtes EF. Voir la doc MSDN.

8) Jointures externes

Pour cela il faut utiliser DefaultIfEmpty, on l’utilise de la manière suivante :

var q = from c in categories

join p in products on c equals p.Category into ps

from p in ps.DefaultIfEmpty()

select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };

III. Divers

1) EF Power Tools

C’est une extension Visual Studio qui permet notamment de :

  • Reverse Engineer Code First : Génère le DBContext, les POCO et le mapping Code First à partir d’une base de données existante (option de base dans VS 2015, via l’ajout d’un modèle ADO.Net)
  • Customize Reverse Engineer Templates : Ajoute le template T4 à votre projet afin de pouvoir customiser la génération de code
  • View Entity Data Model (Read-only) : Affiche une vue du modèle Code First dans le EF designer?
  • View Entity Data Model XML : Affiche l’EDMX XML représentant le Code First.
  • Generate Views : Génère des vues précompilées afin d’améliorer le temps de démarrage de l’application

Plus d’infos ici : https://msdn.microsoft.com/en-us/data/jj593170.aspx

2) Pluralization Service

Vous avez déjà dû le remarquer mais EF possède un algorithme pour mettre aux pluriels les variables, il supporte seulement l’anglais mais vous pouvez faire votre service custom et le pluger à Entity Framework.

Voir cet article pour plus d’infos

 

Voilà, j’espère que vous avez appris quelques petits trucs qui vous faciliteront la vie 😉

Entity Framework : Code First avec Migration 1/2

Entity Framework est pour rappel un ORM (Object RelationShip Manager) qui permet de faire :

  • Le mapping entre la base de données et les classes Entités
  • De proposer les méthodes du CRUD (Create Read Update Delete)

Il existe 3 workflows :

  • dataBase First
  • Model First
  • Code First

Lors de la création d’un projet MVC 4 dans Visual Studio 2012 , EF 5 est intégré par défaut
Cet article a pour but d’expliquer comme implémenter Entity Framework en utilisant le workflow Code First (et générer la base de données)

  1. Code First

    Le workflow Code First consiste à écrire comme son nom l’indique en 1er les classes entités (qui représentent le Model) puis:

  • soit de faire le mapping avec une base de données déjà existante
  • soit à partir de ces dernières de générer la base de données.
  1. Les classes Entités (Model)

    Dans notre exemple nous travaillons sur une application simple de gestion de Music (Music Store)
    Nous notre projets MVC dans le répertoire Models nous allons créer 2 classes qui représentent nos entités comme suit :

    Album.cs

    Genres.cs

  2. La classe de mapping (DbContext)

    Dans Models on crée une classe MvcMusicStoreEntities.cs qui hérite de DbContext, ça représente notre DBcontext



    Dans notre exemple on a fait le mapping :

    Table Albums –> classe Album

    Table Genres –> classe Genre

Lire la suite

[Build 14] – Go Mobile with C# and Xamarin

Mail de John
Vendredi 4 avril 2014 06:10
Go Mobile with C# and Xamarin
Les gens passent 86% du temps sur mobile à utiliser des applications natives contre 14% pour les applications web.

Facebook utilisait le HTML5 pour développer leurs applications mais leurs notes étaient terriblement basses. Une fois qu’ils sont repassés en natif les notes sont passées de 2 à 4 en moyenne.

C# tourne sur 2.6 milliard de devices (tout OS confondus).

 

Explication de comment fonctionne le développement multiplateforme à l’heure actuelle avec le mode en Silo en natif.
On enchaîne avec un court rappel du développement multiplateforme avec les technologies web.
Ensuite présentation de la façon de procèder avec Xamarin et de la liste des APIs disponibles par plateforme (projection des API).
Démonstration du développement d’une application native Ios (Camera, Filtres et Twitter)

 

Quelques statistiques sur le pourcentage de code commun entre les plateformes pour des applications réelles avec explication de pourquoi telle ou telle application à un meilleur pourcentage que sa voisine.

 

Pour partager du code avec Xamarin on peut utiliser des Universal Apps, des PCL simple ou PCL avancée avec NuGet (PCL ne contenant que les définitions du code comme SQLite).

Xamarin est en train de migrer complètement vers des PCL (utilisant le profil 78).
Ajout de certaines API dans Xamarin :

– Mono.Data.Sqlite
– CouchBase
– System.Drawing
– MailKit/MimeKit
– Et bien d’autres à venir
Démonstration de l’application de démo Xamarin Store
Xamarin dispose d’un store de composants accessibles depuis Xamarin Studio (par exemple un composant pour gérer les Google Glass).
Présentation de Xamarin Test Cloud, un outil permettant de tester automatiquement une application Android sur plusieurs centaines de devices.

 

John

[Build 14] – Wrap a Mobile API around your Enterprise and Take Data Offline with NoSQL on Windows Phones and Tablets

Mail de John
Vendredi 4 avril 2014 06:08

Wrap a Mobile API around your Enterprise and Take Data Offline with NoSQL on Windows Phones and Tablets

Quels sont les ingrédients pour la mobilité en entreprise :
– Le meilleur moyen est de penser aux API avant de penser aux Devices
o Les CIO veulent pouvoir utiliser leurs données n’importe où
o Intégrer et orchestrer les diverses API propriétaires dans le Backend
o Apporter la performance et la scalabilité au backend qui n’ont pas été designés pour la scalabilité du web
o Créer des API « mobile-friendly » et les exposer aux appareils mobiles
o Publier les API avec un accès externes pour les appareils mobiles.

 

Comment mélanger des systèmes disparates ?
– Ne pas passer trop de temps pour s’adapter à chaque système en écrivant du code spécifique et non maintenable
– Utilisez des adapters pré-construits de certains EAI comme ceux de SSIS
– Connectez visuellement les différentes sources de données et de destination

Scaling out

Mot clef : Data Sharding
– Pourquoi autoriser des millions d’appareils à surcharger une base de données
o Replication et AlwaysOn
o Il est mieux d’avoir de petits groupes de devices qui se connectent sur de multiples copies de bases
– Filtrer et répliquer les bases, tables et colonnes vers d’autres nœuds SQL Server
o Créer des réplications transactionnelles et en lecture seules pour redimensionner les données
o Utilisation des optimisations mémoire des tables de SQL Server 2014
– Faciliter la géo-réplication des données

Les procédures stockées sont maintenant compilées en code machine.

 

API

– Utiliser des transports multicanaux et des formats de donnée
o REST
o JSON
o Gzip/Deflate

– Construire une couche d’API
o Convertir les API propriétaires et les protocoles en api « mobile-friendly »
o Récupération des données depuis les systèmes du backend
o Sérialiser les objets métiers en JSON
o Précharger les données au lieu de faire des appels fréquents
– Performance + Scalabilité + Disponibilité
o Mettre fréquemment en cache les données avec la classe MemoryCache, Azure Cache, …

Démonstration du développement d’une API avec du cache en C#.

Mobile Access Gateway

– Web App Proxy
o Nouveau rôle pour l’accès à distance
o Se situe dans la DMZ entre les firewalls frontaux et internes
o Fonctionne avec ADFS afin de publier de manière sécurisée des services utilisant une authentification Kerberos ou
« claim »
o Un reverse proxy redirige les requêtes

 

Consumation des API et mode déconnecté avec NoSQL

– HttpClient est votre nouvel ami
o Rest, Auto-decompression, JSON

– Utilisation de tables NoSQL pour implementer le mode hors ligne pour les téléphones et tablettes
o Mode offline
o Utilisation de Linq sur les objets en mémoire

Démonstration d’une application phone utilisant un service et sauvegardant les données en local.
John

[Build 14] – Multitasking and Background Processing on Windows Phone

Mail de John
Jeudi 3 avril 2014 10:56

Multitasking and Background Processing on Windows Phone

On commence par un petit rappel du model de multitasking dans Windows Phone 8.
S’ensuit un rappel du modèle d’exécution des tâches de fond dans WinRT (Processus séparés, réponds à des Triggers et à des conditions).

Présentation des triggers disponibles dans Windows Phone.
Comment créer une tâche de fond ?
– Implémenter IBackgroundTask.
– Modifier le Manifest pour activer l’accès aux tâches de fond.

Démonstration en C# de création d’une backgroundtask et comment on l’enregistre dans le système (BackgroundExecutionManager.RequestAccessAsync), l’ajout de triggers (BackgroundTaskBuilder, SystemTrigger, SystemCondition). Ensuite démonstration de comment lancer une backgroundtask en Javascript (Ajout de la définition de la propriété TaskEntryPoint du BUilder qui correspond au fichier js contenant la tâche).

Les tâches de fond natives (aka WinRT) sont disponibles dans les applications Silverlight 8.1. Les BackgroundAgents sont maintenant hébergés par l’infrastructure WinRT.

Accès aux Sensors, Bluetooth LE, RFCoom même si l’application n’est pas en premier plan.
Basé sur les nouvelles API Bluetooth WinRT.

Nouveau triggers :
– GattCharacteristicNotificationTrigger
– DeviceChangeTriggfer
– DeviceUpdateTrigger
– RfcommConnectionTrigger

Les notifications de Geofencing peuvent être reçues en background dans une tâche de fond.
Ajout des Push Triggers dans Windows Phone.
Associer une Background Task avec un WNS channel.
Activation d’une tâche de fond grâce à une notification push raw.

Démonstration des Push Notifications.

Le rendu XAML dans les BackgroundTasks est maintenant possible ! (Démonstration de ceci en C++ c’est mieux pour la mémoire).

BackgroundTransfer
– Windows.Networking.BackgroundTransfer
– Pas de restriction de taille de fichiers
– Support du multi part mime (pour les gros fichiers)
– Verbes HTTP supplémentaires (PUT, RETR, STORE) et aussi FTP
– In-progress stream access
– Data-Sense and Battery Save aware

Non disponible pour les applications Windows XAML :
– Continuous Background Location
– Runs-Under-Lock
– VoIP Agents
– Wallet Agents

Economiseur de batterie :
Permet de trier et de gérer les applications qui tournent en tâche de fond et de voir leurs utilisations de ressources

Contraintes de ressources :
– Toutes les tâches de fond ont des quotas CPU, mémoire et réseaux
– Les quotas sont basés sur l’utilisation actuelle du CPU au lieu d’une limite d’horloge
– Le quota d’horloge sera renforcé (au moins une fois toutes les 30 secondes)
– Le quota de mémoire s’adapte aux capacités de chaque device.
– Le TimeTrigger aura un temps d’exécution assuré d’un maximum de 30 minutes maximum.
Appelez RequestAccessAsync() pour avoir votre quota maximum.
John

 

Utilisation de Log4net dans un projet MVC

Dans ce post je vais vous montrer comment implémenter un mécanisme de log dans des fichiers textes avec la librairie log4net et ceci très rapidement.

Récupération de Log4net

Dans le package manager on récupère le package log4net, soit via le Manager de packages Nuget


Soit via le Package Manager Console en lancer la commande:
Install-Package log4net

La dll est alors importée dans les références



Configuration

Pour modifier le fichier web.config qui va contenir la config de log4net pour écrire dans un fichier texte on va récupérer un autre package nuget

Log4net RollingFileAppender

Ou

Install-Package log4net.samples.rollingfileappender

Dans notre fichier Web.config, on a bien


Il faut modifier la valeur de <file value…> avec le chemin du fichier de log.

Exemple :



Global.Asax

Dans le fichier global.asax dans la méthode Application_Start , il faut rajouter

log4net.Config.XmlConfigurator.Configure();

Cela permet de cabler log4net avec la config établie dans le web.config
Controller

Dans le controller dans lequel on désire utiliser log4net,

On déclare une variable

private log4net.ILog log = log4net.LogManager.GetLogger(typeof(HomeController));

Puis dans la methode (Action) pour écrire le log
//exemple debug
log.Debug("Ceci est un log de Debug");
//exemple information
log.Info("Ceci est un log d'information");

Test

Pour
tester on execute notre page , et on voit bien le fichier de log


Et son contenu


Voila on vient de mettre en place un système log dans un fichier texte très rapidement.

Voir aussi:

http://www.codeproject.com/Articles/140911/log-net-Tutorial
http://www.codeproject.com/Articles/34287/log-net-C-Code-Snippets

Détails de la structure d’un projet MVC 4

Ce post a pour but de présenter les différents répertoires qui représentent un projet MVC 4

Tout d’abord voici la structure complète d’un projet MVC 4

Image sans titre

Certains de ces répertoires : bin et obj ne sont pas visibles par défaut, il faut dans l’explorateur de solution, choisir de voir tous les fichiers

Cette structure se compose en 5 grandes parties

Lire la suite