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' go
type_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_TYPE
ouTYPE_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_adonet2
dans 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_adonet2
dans la basesybsystemprocs
avecGetSchema
: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
GetSchema
pour le "reverse". - Si elle existe, appel de la procédure stockée
sp_oledb_columns_adonet2
avec les bons paramètres pour simuler ce que retourneraitGetSchema
en 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.