septembre
2007
J’ai eu la surprise de constater que, même certaines personnes très pointues techniquement que ce soit sur .NET et / ou sur SQL n’avaient pas compris le principe de LINQ To SQL.
Je pense donc qu’une petite explication s’impose.
Avant de commencer, précisons que nous n’aborderons pas le sujet de LINQ To Entities ici.
Les développeurs et DBA avec qui j’ai parlé pense que l’ADO .NET 3.5 passe forcément par LINQ To SQL. C’est faux !!! Ce n’est pas pour rien que des modifications ont été apportées sur les DataSets. (http://blog.developpez.com/index.php?blog=121&title=les_datatable_generees_par_le_designer_d&more=1&c=1&tb=1&pb=1 et http://blog.developpez.com/index.php?blog=121&title=encore_des_modifs_avec_les_datasets&more=1&c=1&tb=1&pb=1)
LINQ To SQL ne gère pas de cache. Cela implique qu’à chaque fois qu’on va vouloir accèder aux entitées, une requête est générée. Prenons un exemple. Le code suivant :
Console.WriteLine("{0} {1}", p.LastName, p.FirstName);
foreach (var p in context.Persons)
Console.WriteLine("{0} {1}", p.LastName, p.FirstName);
va envoyer les requêtes suivantes à la base de données :
SELECT [t0].[Id], [t0].[LastName], [t0].[FirstName], [t0].[BirthDay], [t0].[Adress1], [t0].[Adress2], [t0].[Postal], [t0].[City]
FROM [dbo].[Person] AS [t0]
— Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1
SELECT [t0].[Id], [t0].[LastName], [t0].[FirstName], [t0].[BirthDay], [t0].[Adress1], [t0].[Adress2], [t0].[Postal], [t0].[City]
FROM [dbo].[Person] AS [t0]
— Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1
Une fois qu’on a compris cela, on a compris que les DataSets n’étaient pas mort.
Pour aller encore plus loin, si j’insère un Add sur la System.Data.Linq.Table<Person> persons entre mes deux foreach, les résultats de ceux-ci resteront identiques et ma nouvelle personne sera ignorée tant que je n’aurai pas commité les modifications de mon DataContext via un SubmitChanges().
LINQ To SQL doit être systèmatisé dans des données critiques sur lesquelles on a un fort risque d’accès concurrents.
Les DataSets doivent être privillégiés dans le cas de données sans accès concurrents et très souvent utilisées.
Pour rappel, le DataSet va stocker en mémoire deux copies de vos données : l’originale et la donnée modifiée. Aussi, il faut éviter de charger trop de données dans un DataSet à moins d’avoir beaucoup de mémoire
LINQ To SQL a, à mon avis au moins un avantage indéniable par rapports au DataSet : le typage.
Premièrement, les columns autorisant la valeur null génèrent des propriétés de type Nullable<T>, ce qui évite le « vilain » row.IsNull(« myColumn ») à tester
avant de récupérer les valeurs d’un DataRow.
Deuxièmement, le fait d’avoir des entités (directement gérées par le designer) permet d’avoir (sans rien faire) des relations directement sur les entités et non pas sur les columns formant la clé étrangère.
Bien entendu, il est possible d’implémenter des entités qui encapsule de DataSet et de faire la même chose. L’avantage de LINQ To SQL c’est que le designer intégré dans Visual Studio 2008 génère ces entitées pour nous.
Quelque chose qui peut choquer certains développeurs et encore plus les DBAs c’est le fait d’avoir un SubmitChanges() sur le DataContext et pas de RejectChanges(). La première fois qu’on m’a posé la question, j’ai proposé de réinstancier le context, proposition qui s’est retrouvée confrontée à une levée de boucliers de la part des DBAs. Après réflexion, cela ne me choque pas du tout. Une fois de plus on ne stocke pas de données avec LINQ To SQL par conséquent, réinstancier le DataContext pour annuler la transaction ne me parait pas si choquant.
Rappelons quand même que, même si c’est pas vraiment le but, on peut travailler en déconnecté avec LINQ To SQL.