Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Windows Phone : les bases de données locales

[new:30/05/2014]Depuis la version 7.1 Windows Phone offre une gestion de base de données intégrée manipulable en LINQ. Peu de développeurs semblent en connaitre l’existence et encore moins la façon d’en tirer le meilleur parti alors qu’on la retrouve bien entendu sous Windows Phone 8 et 8.1. Bonne occasion de faire le point sur cette fonctionnalité !Plus...

Un Parser SQL Gratuit, et un beautifier en prime

[new:30/06/2011]On parle tellement de technologies avancées comme Entity Framework qu’on en oublie parfois qu’au bout de la chaine ce bon vieux SQL existe toujours et que plus souvent qu’on le croit il faut en écrire, voire en mettre en forme, et plus difficile encore, en parser. Mais parser SQL est une tâche très difficile. Sauf si on ruse un peu...Plus...

Entity Framework et la compatibilité arrière (problème Datetime2).

[new:05/07/2010]Vous possédez un OS récent, comme Windows 7, vous développez avec les outils les plus modernes (disons VS 2010 au hasard) et, bien entendu votre base de données installée en local est SQL Server 2008. D’une part parce que c’est une bonne version, mais surtout parce que vous n’avez pas trop le choix… Vous créez une application pour un client qui utilise SQL Server 2005 et là, pof! dès qu’il exécute votre logiciel il y a une exception du genre “The version of SQL Server in use does not support datatype 'datetime2”… Plus...

Un éclairage sur les techniques d'accès aux données sous .NET

Depuis la sortie de .NET Microsoft n'arrête plus sa course folle ! La plupart des technologies publiées faisaient partie d'un plan presque totalement connu à l'avance, comme WPF, WCF etc. Il a fallu du temps pour qu'émerge ses "modules" de .NET car même le plus puissant des éditeurs de logiciels du monde ne peut pas releaser la totalité d'une montagne comme .NET en un seul morceau. S'il était clair que WPF serait la nouvelle gestion des interfaces utilisateurs et que Windows Forms n'était qu'un "os à ronger" en attendant, le foisonnement des technologies tournant autour des données n'était pas forcément visible ni prévisible il y a quelques années. Et même aujourd'hui savoir ce qui existe et comment s'en servir avec l'ensemble des autres technologies n'est pas forcément une mince affaire !

Un petit dessin valant tous les discours, voici un diagramme qui tourne sur les blogs américains de Microsoft et que j'ai en partie traduit pour vous, en espérant que cela vous aidera à y voir plus clair !

Quelques précisions pour certains acronymes ou noms de technologies :

[Faite un clic-droit sur l'image et copiez-la pour l'afficher en 100% dans Word ou autre ]

Comment passer outre la limitation du DISTINCT sur un SELECT contenant un champ text sous SQL Server

Voici un billet moins "hi-tech" que d'habitude. Point de LINQ dans tout çà, juste un bon server SQL SERVER, une table contenant un champ Text ou NText et une bête requête qui peut retourner plusieurs fois le même enregistrement. Et comme on ne désire pas voir les copies éventuelles, bien entendu on place instinctivement une clause DISTINCT dans le SELECT.

C'est beau, simple comme SQL... Sauf que... SQL Server n'aime pas du tout la clause DISTINCT s'il y a un champ texte dans le SELECT. Et pour cause, il ne sait pas comment comparer les contenus, du coup point de DISTINCT possible.

Quelques bonnes âmes vous conseilleront peut-être :

a) de changer tous vos champs texte en varchar
b) de vous passer du champ texte dans le SELECT et de l'obtenir à part dans une autre requête

Les conseilleurs ne sont pas les codeurs ! Les varchar ont une limite de 8000 caractères et il n'est pas toujours possible de les substituer à Text/NText. De plus modifier tous les champs de ce type dans une application peut être un énorme travail (code, procédures stockées, vues, tout cela à mettre à jour). Solution bidon donc.

Quant à faire le SELECT DISTINCT sans les champs texte puis à faire une seconde requêtre derrière pour les obtenir, c'est franchement lourd et pas forcément sans conséquence sur le code appelant (qui doit faire autant de sous requêtes que de records pour obtenir les champs texte, et les stocker, etc).

Non, il existe plus simple, et un peu plus vicieux : faire une jointure de la table sur elle même.

Oui, tout simplement. L'astuce consiste à faire un select dans la table de tous les champs (y compris les champs texte) mais sans la clause DISTINCT, table qu'on lie à elle même mais ce coup ci en faisant un SELECT DISTINCT qui lui omet les champs texte... La feinte est bonne, mais elle ne saurait faire de miracle, en effet, les champs texte ne seront pas utilisés pour faire la DISCTINCTion entre les records. Cette solution n'a donc qu'un seul hic : elle ne peut pas fonctionner si vous voulez vraiment que le DISTINCT prenne en compte les champs texte. Là je n'ai pas vraiment d'astuce à vous proposer. Mais pour les autres, voici un bout de code SQL fictif qui vous montrera la syntaxe à utiliser :

SELECT t1.c1, t1.c2, t1.LeChampTexte
FROM MaTable t1 JOIN
     (SELECT DISTINCT c1,c2 FROM MaTable WHERE Desc LIKE 'Test%') AS t2
     ON t1.c1 = t2.c1

on suppose ici que le champ "c1" représente la clé (il peut s'agir de plusieurs champs, of course, à vous d'adapter le code), que le champ "c2" est un autre champ sur lequel le DISTINCT portera et que "LeChampTexte" ... est le champ texte qui pose problème. On voit mieux ici que le DISTINCT ne sera effectué que sur "c1" et "c2". Mais cela permet bien de faire un DISTINCT tout en retournant les champs texte, le tout en une seule requête...

Bon SQL et... Stay Tuned !

Présentation des différentes facettes de LINQ (article à télécharger)

Le voilà enfin ! [Updated ! Version 1.1 en ligne]

un PDF de 32 36 pages et 5 6 projets exemples sous VS 2008 pour vous présenter les différentes facettes de LINQ. Je n'en voyais plus le bout de cet article ! Non par lassitude, bien au contraire, mais parce que LINQ est d'une incroyable richesse et que je voulais vous en dire la maximum.

Sans entrer dans les détails trop techniques de la syntaxe (la doc Microsoft est très complète et n'a nul besoin d'une redite), cet article présente le pourquoi et le comment de LINQ au travers d'explications et d'exemples de code.

  • LINQ to Objects
  • LINQ to SQL
  • LINQ to Dataset
  • LINQ to XML
  • LINQ to Entities

Sans prétendre que toutes ces versions de LINQ n'auront plus de secret pour vous après avoir lu l'article, vous en saurez certainement plus pour mieux comprendre pourquoi il y a eu un avant LINQ et qu'il va y avoir un après LINQ...

Pour télécharger l'article cliquez ici !

Avant de lire cet article il est préférable de connaître les nouveautés syntaxiques de C# 3.0, si ce n'est pas votre cas vous pouvez télécharger mon précédent article.

Pour la liste de tous mes billets sur LINQ cliquez ici.

Note de la version 1.1 : table des matières ajoutée + plus de détails sur Linq to Entities et un projet utilisant la bêta 3.

SQL Server 2008 et le type FileStream - résumé de la conférence DAT304 des TechEd 2007

Gérer des données "raw" tels que des fichiers multimédia, de la documation, etc, dans une base de données est un sujet qui divise les développeurs depuis longtemps. SQL Server 2008 va (enfin) mettre fin à cette dispute de principe !

DAT304 - Managing Unstructured Data in SQL Server 2008: Introducing the Filestream Datatype

Je n'ai suivi que partiellement cette conférence, il faudra d'ailleurs que je profite de la diffusion en ligne des vidéos pour les participants aux TechEd pour la regarder en totalité. Ce qui m'intéressait c'était l'info elle-même qui se résume à un nouveau type champ dans SQL Server. Mais c'est une avancée de taille, je vais vous expliquer pourquoi en quelques lignes...

Le duel blob vs file system pour les données raw

En effet, il y a d'une côté les tenants du "tout file system" c'est à dire le stockage des fichiers en dehors de la base de données avec juste le stockage des noms de fichiers dans la base elle-même. Pour: la simplicité, la gestion des flux du file sytem généralement plus performante que les blobs. Contre: le manque cruel de consistence, pas de contexte transactionnel, backups à faire séparément, etc, etc. Je fais partie des "anti" d'ailleurs.

De l'autre côté il y a ceux qui préfèrent le stockage en blob. Pour : consistence des données, contexte transactionnel, backup unique, etc. Je pour pour cette solution en général. Contre : les blobs sont moins rapide en lecture / écriture de flux que le file system, certains SGBD imposent des limites à la taille des blobs. Si on fait abstraction de ce dernier argument (il suffit d'utiliser une base n'ayant pas cette limite, par exemple SQL Server 2005 ou même Firebird/Interbase), le léger inconvénient de la rapidité (qui reste modeste et peu gênant dans la plupart des cas) est largement, à mon avis et par expérience, compensé par les avantages de cette technique. Reste qu'on peut faire mieux...

Mélanger le meilleur des deux solutions 

C'est justement ce que propose SQL Server 2008 avec le nouveau type FileStream qui est une extension de VARBINARY(MAX) qui s'en distingue par un attribut lors de la création du champ.

Le principe est simple : on marie le meilleur des deux solutions existantes. On prend la souplesse (gestion des quotas par ex) et la rapidité du file system (NTFS obligatoirement) et on l'associe à la cohérence des données de la solution blob. En gros, SQL Server 2008 stocke les fichiers dans le file system mais assure l'accès à ces fichiers comme à n'importe quel autre champ ce qui permet la gestion transactionnelle, le backup unique et centralisé.

Conclusion 

Une solution simple et performante à un problème de plus en plus crucial, les utilisateurs devant de plus en plus gérer des données lourdes (photos, documents digitalisés, vidéos...) en synchronisme parfait avec les bases de données. Une fichier client peut comporter une photo, une fiche article une vidéo de présentation, tout cela n'est plus "exotique", cela devient une contrainte légitime d'exploitation.

Pour l'instant SQL Server 2008 est en bêta, mais comme son nom l'indique il devrait être bientôt sur le marché...

Encore une bonne idée, ingénieuse et simple à mettre en oeuvre. Je trouve que les équipes de dev de MS ont vraiment l'âme créative depuis qu'on est entré dans ce que j'appelle "l'ére .NET". Souhaitons que ça dure le plus longtemps possible !

A+ pour un nouveau billet. Stay tuned !

Pister les modifications de schéma (SQL Server)

Maintenir une base de données est toujours délicat notamment en raison des modifications de schéma parfois nécessaires durant le développement d'une application ou sa maintenance.

De même il peut s'avérer utile de pister, chez un client/utilisateur, toute modification du schéma qui pourrait destabiliser l'application (tout en rendant celle-ci coupable des problèmes éventuels, donc engageant votre responsabilité...).

Reconstruire l'historique des modifications de schéma pour ensuite les centraliser dans un script de mise à jour de la base de données peut aussi être un plus très appréciable.

Mais comment pister et conserver ces modifications et où les stocker de façon sûres ?

Avec SQL Server la réponse tient en un simple trigger et en l'utilisation habile du type de donnée XML !

Vous l'avez compris le suivi des modifications sera stocké dans la base elle-même, pratique et fiable cela évite la présence de fichiers annexes risquant d'être perdus.

Etape 1 : Créer la table pour stocker les modifications

CREATE TABLE [Audit].[ModifSchema](

[EventID] [int] IDENTITY(1,1) NOT NULL,
[EventData] [xml] NULL,

PRIMARY KEY CLUSTERED
(
   [EventID]
ASC
) WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

Etape 2 : Créer le trigger

CREATE TRIGGER [Trig_AuditModifSchema]
ON
DATABASE
FOR
DDL_DATABASE_LEVEL_EVENTS
AS
INSERT
INTO Audit.ModifSchema(EventData
)
SELECT EVENTDATA
()
GO
ENABLE TRIGGER [Trig_AuditModifSchema] ON DATABASE

Etape 3 : il n'y a pas d'étape 3 c'est FINI !

Désormais, lors de toute modification du schéma de la base de donnée un événement sera enregistré dans la table et il sera possible de consulter, sous la forme d'une entrée XML facilement lisible et analysable par tout outil ou portion de code, l'ensemble des modifications. Voici un exemple : 

<EVENT_INSTANCE>
    <
EventType>ALTER_TABLE</EventType
>
    <
PostTime>2007-06-03T20:12:05.813</PostTime
>
    <
SPID>55</SPID
>
    <
ServerName>CHI100906</ServerName
>
    <
LoginName>MYDOMAIN\myusername</LoginName
>
    <
UserName>dbo</UserName
>
    <
DatabaseName>Sales</DatabaseName
>
    <
SchemaName>dbo</SchemaName
>
    <
ObjectName>Products</ObjectName
>
    <
ObjectType>TABLE</ObjectType
>
    <
TSQLCommand
>
        <
SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON"      QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE"
/>
        <
CommandText>
ALTER TABLE dbo.Products
    DROP COLUMN testremove
       </CommandText
>
  </
TSQLCommand
>
</
EVENT_INSTANCE>

A noter, la fonction EVENTDATA() est fournie par SQL Server à l'intérieur d'un trigger DLL et renvoie toutes les données sous la forme d'un document XML.

Cette idée astucieuse a été publiée par plusieurs auteurs sous différentes formes, je ne m'en attribue pas la paternité. On la retrouve par exemple sur le Richard's C# blog, un blog riche que je conseille pour ceux qui lisent l'anglais, of course.

 

kick it on DotNetKicks.com