Introduction
La procédure stockée sp_oledb_columns change entre les versions 15.0.2 et
15.0.3 de Sybase Adaptive Server Enterprise. Ces modifications ont des impacts
sur la méthode ADO.NET GetSchema de la classe ASEConnection du pilote ADO.NET
2.0 de Sybase (Sybase.AdoNet2.AseClient.dll).
Cet article passe en revue les modifications dans la procédure stockée
sp_oledb_columns entre les versions 15.0.2 et 15.0.3 et les impacts potentiels
sur les applications existantes développées en C# et utilisant la méthode
GetSchema pour effectuer du "reverse" des objets (tables, procédures, etc.).
Si l’application C# exploite les résultats de GetSchema dans un environnement
de développement ASE 15.0.3, celle-ci aura un comportent inattendu si la
production est encore en version ASE 15.0.2.
La méthode GetSchema de la classe AseConnection du driver ADO.NET 2.0 de Sybase
Le driver ADO.NET 2.0 de Sybase
Le driver ADO.NET 2.0 de Sybase est disponible dans le SDK Open Server et Open Client Sybase 15.0 à partir de l’ESD #10. Pour plus d’informations : Open Server, Open Client, and SDK 15.0, New features in ESD # 10 (ADO.NET 2.0 support).
La documentation sur les APIs du driver ADO.NET 2.0 pour Sybase ASE est disponible dans la documentation Software Developer’s Kit 15.5 : Software Developer’s Kit 15.5,ADO.NET Data Provider 2.155 User’s Guide.
Sybase.AdoNet2.AseClient.dll et sybdrvado20.dll sont les 2 DLLs vitales du
driver ADO.NET 2.0 de Sybase ASE, DLL à embarquer dans la GAC ou l’IDE Visual
Studio lors des développements.
La méthode GetSchema de la classe AseConnection
La méthode GetSchema de la classe AseConnection permet de faire du "reverse"
avec C# des objets de bases de données afin de récupérer leurs caractéristiques
et de les exploiter. Elle récupère les collections de méta-données (MetaData
Collections), les collections les plus courantes sont :
|
|
Voici un exemple de code simple afin de récupérer en C# les colonnes de la
table SECURITIES_CHAR dans la base GSSA avec leurs caractéristiques grâce à la
méthode GetSchema :
AseConnection connection = new AseConnection("Data Source=FRDGLO101;Port=30003;Initial Catalog=GSSA;User Id=sa;Password=******");
connection.Open();
DataTable SchemaTable = connection.GetSchema("Columns", new string[] { "SECURITIES_CHAR" });
le résultat est ensuite affiché dans la console, ligne par ligne, colonne par colonne :
foreach (DataRow row1 in SchemaTable.Rows)
{
foreach (DataColumn col in SchemaTable.Columns)
{
Console.WriteLine(col.ToString() + " = " + row1[col].ToString());
}
}
sp_oledb_columns, différences entre les versions 15.0.2 et 15.0.3
La procédure stockée sp_oledb_columns est installée dans la base
sybsystemprocs par le script installmaster des distributions ASE
($SYBASE/$SYBASE_ASE/scripts) et elle est utilisée par les couches clientes
OLE-DB et ADO.NET. sp_oledb_columns retourne au client les caractéristiques
d’une ou des colonnes pour une table donnée.
À partir de la version 15.0.3, un nouveau paramètre @is_ado en 5è position
est implémentée pour la procédure sp_oledbcolumns.
| Prototype ASE 15.0.2 sp_oledb_columns | Prototype ASE 15.0.3 sp_oledb_columns |
|---|---|
|
|
Ce nouveau paramètre @is_ado de la version 15.0.3 est par défaut à 1
lorsqu’il n’est pas donné. Pour le moteur ASE, cela signifie que la couche
ADO.NET cliente est la version 1 par défaut si le client ne lui notifie pas la
version majeure ADO.NET.
Le nouveau paramètre @is_ado n’est pas anodin car il ne retourne pas les
mêmes jeux de résultats pour @is_ado=1 et @is_ado=2. Il suffit de consulter le
code source de la procédure sp_oledb_columns pour mieux le comprendre.
Pour la version 1, le type de la colonne est donné avec l’entête DATA_TYPE
et l’identifiant du type (129 pour varchar).
Pour la version 2, le type de la colonne est donné avec l’entête TYPE_NAME
et le nom explicite du type de la colonne (varchar).
| sp_oledb_columns ASE 15.0.2 | sp_oledb_columns ASE 15.0.3 @is_ado=1 | sp_oledb_columns ASE 15.0.3 @is_ado=2 |
|---|---|---|
|
|
|
Le résultat des exemples ci-dessus est allegé pour la lisibilité.
L’identifiant 129 pour le type varchar provient de la table
sybsystemprocs..spt_sybdrv :
select * from sybsystemprocs..spt_sybdrv where type_name='varchar' gotype_name data_type tds_type -------------------- ----------- ----------- varchar 129 39
Interactions entre la méthode GetSchema du pilote ADO.NET 2 et sp_oledb_columns
La méthode GetSchema de la classe AseConnection s’appuie sur les procédures
systèmes sp_oledb_% dans la base sybsystemprocs (sp_oledb_databases,
sp_oledb_columns, sp_oledb_stored_procedures…) pour réaliser son "reverse
engineering".
Pour les colonnes d’une table, sp_oledb_columns est appelée : une simple
trace RIBO, un audit ou la consultation des tables MDA suffit à la détecter
:
| Appel GetSchema ADO.NET 2 | Appel en base |
|---|---|
|
|
Problématique et contournement
Dans le cas où l’application C# est développée et en recette dans des
environnements ASE 15.0.3 et qu’elle exploite TYPE_NAME retourné par
sp_oledb_columns, le problème peut se poser si cette application monte dans des
environnements de production ASE encore en version 15.0.2, version pour
laquelle sp_oledb_columns retourne un identifiant pour le type dans la colonne
DATA_TYPE => crash et application non opérationnelle.
Sortir l’artillerie lourde consisterait à détecter en C# si la méthode
GetSchema appelle sp_oledb_columns en version 15.0.2 ou 15.0.3 en réalisant les
opérations ci-dessous :
- Détection du nom de la colonne retournant le type de la colonne :
DATA_TYPEouTYPE_NAME. - Manipulation d’un tableau de transcodification : 129 équivaut à varchar, etc.
Le temps que les environnements de production soient migrés vers la version 15.0.3, une solution très temporaire est envisageable, en voici les étapes :
- Création de la procédure
sp_oledb_columns_adonet2dans la base sybsystemprocs des environnements ASE 15.0.2, procédure dont le code est celui de laversion 15.0.3. - Détection en C# de l’existence de la procédure stockée
sp_oledb_columns_adonet2dans la basesybsystemprocsavecGetSchema:connection.ChangeDatabase("sybsystemprocs"); DataTable SchemaTable = connection.GetSchema("Procedures", new string[] { "sp_oledb_columns_adonet2" }); - Si elle n’existe pas, exécution classique de la méthode
GetSchemapour le "reverse". - Si elle existe, appel de la procédure stockée
sp_oledb_columns_adonet2avec les bons paramètres pour simuler ce que retourneraitGetSchemaen version 15.0.3.
Une recompilation de l’application est inévitable.
Lorsque l’intégralité du parc est migré en version 15.0.3 : supprimer la
procédure sp_oledb_columns_adonet2 et le bout de code C# détectant l’existence
de celle-ci.