Envoyé par
JackIsJack
Bonjour,
J'utilise SQL Server dans le cadre d'application web et je me pose la question suivante :
-> Faut-il insérer de la logique métier dans des procédures stockées ?
C'est une question mainte fois débattue, qui dépend de ce que vous voulez faire :
- obtenir d'excellentes performances
- ou vous faire plaisir avec un modèle idéologiquement parfait...
Malheureusement l'un ne va pas avec l'autre !
Il me semble que le schéma sécurisé pour modifier des données dans une base est d'avoir :
- une application qui interroge une base de données,
- puis elle instancie des objets avec les données qu'elle a récupéré
- fait des modifications sur ces objets
- l'application contrôle à l'enregistrement que les données sont cohérentes vis-à-vis du modèle
- et si c'est ok : l'application ordonne les modifications de données dans la base.
ça c'est l'idéologie... Mais elle ne résiste pas une minute à une analyse sérieuse... En effet vous indiquez que c'est à l'application de contrôler la cohérence. Ceci est strictement impossible à faire dans un monde ensembliste et multi utilisateur (le SGBDR) par l'application (qui est un monde itératif et mono utilisateur).
En effet, en dehors des contraintes de domaine (vérifier qu'une information unique et atomique est dans les clous), tous les autres contrôles sont impossible à établir dans une application....En d'autres termes, la cohérence est du ressort du SGBDR et de rien d'autre, si vous voulez une base intègre.
Un seul exemple...
L'utilisateur A visionne des données de début et de fin d'un process (id 456) avec les données suivantes :
1 2 3
| USER A...
Début : 20h56
Fin : 23h21 |
L'utilisateur B, visionne les mêmes données :
1 2 3
| USER B...
Début : 20h56
Fin : 23h21 |
A modifie maintenant la date de fin :
1 2 3
| USER A...
Début : 20h56
Fin : 22h48 |
B modifie maintenant la date de début :
1 2 3
| USER A...
Début : 22h51
Fin : 23h21 |
L'application contrôle bien que la date de fin vue dans le formulaire de A est supérieure à la date de début et la commande SQL Suivante est lancée :
UPDATE MaTable SET Fin = 22h48 WHERE ProcessID = 456
L'application contrôle bien que la date de début vue dans le formulaire de B est inférieure à la date de début et la commande SQL Suivante est lancée :
UPDATE MaTable SET Fin = 22h48 WHERE ProcessID = 456
Nous nous retrouvons dans la base avec une incohérence qui fait que la date de début est ultérieure à la date de fin...
Le seul moyen de garder la cohérence des données est d'intégrer les règles dans la base puisque c'est le point focal de toutes les données, sous la forme de contraintes. Dans notre cas :
ALTER TABLE MaTable ADD CONSTRAINT CK_DEB_FIN CHECK(Début <= Fin);
Il n'existe pas d'autre solution viable...
Sauf que voilà, à mon travail, je vois des procédures stockées qui font des update, des delete,...
Rien n'indique que ces modifications n'altèrent pas la cohérence des données.
Bien au contraire ! Car ce sont les contraintes qui protège la base des incohérences. En sus, exécuter du code manipulant les données au sein même du SGBDR est incommensurablement plus rapide que de passer à travers un réseau de multiples fois pour vérifier unitairement telle ou telle condition... En fait 99% du temps serait dans ce cas des "round trips". C'est d'ailleurs ce qui fait les choux gras de notre métier d'expert et nous permet de vendre moult audits dans lequel on réapprends aux développeurs à travailler proprement !!!
1/ Je suppose que c'est pour des raisons de performance que ces traitements sont situés côté serveur
Cela prend du temps de peupler des objets, de transférer des données, de contrôler que l'état final de chaque objet est clean.
Oui
J'ignore s'il existe des façons rapides et propre de réaliser des actions de masse par le biais d'une application.
Aucune... Les application fonctionnement de manière itératives c'est à dire ligne par ligne. Les SGBDR fonctionnement de manière ensembliste, c'est à dire par bloc (les mêmes valeurs ne sont traitées qu'une seule fois dans le lot) voire en parallèle...
Et c'est souvent même pire que ce que vous imaginez car si en plus on a emballé le tout dans une transaction, alors les blocages sont maintenus pendant tout le traitement et comme il prendre 99 fois plus de temps que s'il était encapsulé dans une procédure, alors la concurrence d'accès en prend un coup plus que sévère se traduisant par des blocages, de la contention (files d'attente) voir des verrous mortels (interblocages)... bref, l'horreur !
2/ Ou alors cela signifie qu'il n'y a pas de contrôle de cohérence dans l'application supplémentaire à ceux qui sont dans la base de données : type des données, clef unique, intégrité relationnelle, valeur.
OUI !!!! ça commence à faire tilt dans votre tête...
Dans ce cas-là, il me semble inutile d'avoir un quelconque modèle objet dans l'application ; autant faire du clic bouton = requête.
Vous arrivez à la bonne conclusion !
Comment gérer-vous ces problématiques ? (si vous les gérer)
Merci...
Il suffit d'implémenter le maximum de contrainte dans la base, envoyer les requêtes ou appeler les procédures et attendre la réponse...
Notez bien que sis les SGBDR ne sont pas objet, on peut s'en approcher de très près par le biais des vues, des procédures et des déclencheurs "INSETAD OF". Bref, faire du mapping relationnnel objet (ORM) à l'intérieur du SGBDR... Pour continuez cette analyse je vous propose la lecture d'un article écrit il y a déjà longtemps sur le sujet :
http://sqlpro.developpez.com/cours/b...s-epaisses.pdf
Je vais vous poser une petite question pour vous montrer que les développeurs oublient toujours quelque chose... Voici un code que l'on va dire applicatif :
1 2 3 4 5 6 7
| ObjQuery.QueryText('SELECT * FROM MaTable WHERE Clef = 234');
ObjQuery.exec;
if ObjQuery.DataSet.IsEmpty
then
ObjQuery.QueryText('INSERT INTO MaTable (Clef) VALUE (234)');
ObjQuery.exec;
end; |
Qui est censé ne rentrer que des valeurs de clef sans doublon... Ce code va t-il fonctionner correctement ?
A +
Partager