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.
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 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=PARDGLO101;Port=30000;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());
}
}
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 |
|---|---|
CREATE PROCEDURE sp_oledb_columns (
@table_name varchar(771) = null,
@table_owner varchar(32) = null,
@table_qualifier varchar(32) = null,
@column_namevar char(771) = null )
AS
|
CREATE PROCEDURE sp_oledb_columns (
@table_name varchar(771) = null,
@table_owner varchar(32) = null,
@table_qualifier varchar(32) = null,
@column_name varchar(771) = null,
@is_ado int = 1 )
AS
|
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 |
|---|---|---|
exec sp_oledb_columns
@table_name = "SECURITIES_CHAR",
@column_name = "SEDOL_CODE"
go
DATA_TYPE
---------
129
|
exec sp_oledb_columns
@table_name = "SECURITIES_CHAR",
@column_name = "SEDOL_CODE",
@is_ado = 1
go
DATA_TYPE
---------
129
|
exec sp_oledb_columns
@table_name = "SECURITIES_CHAR",
@column_name = "SEDOL_CODE",
@is_ado = 2
go
TYPE_NAME
---------
varchar
|
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
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 |
|---|---|
DataTable SchemaTable =
connection.GetSchema("Columns", new string[] { "SECURITIES_CHAR" });
|
sp_oledb_columns @table_name="SECURITIES_CHAR", @table_owner=null, @table_qualifier=null, @column_name=null, @is_ado=2 |
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 :
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 :
connection.ChangeDatabase("sybsystemprocs");
DataTable SchemaTable = connection.GetSchema("Procedures", new string[] { "sp_oledb_columns_adonet2" });
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.
| Version | Date | Commentaires |
|---|---|---|
| 1.0 | 06/2010 | Version initiale |
OpenServer, Open Client, and
SDK 15.0, New features in ESD # 10, ADO.NET 2.0 support
Software Developer's Kit 15.5,
ADO.NET Data Provider 2.155 User's Guide
Software Developer's Kit 15.5,
ADO.NET Data Provider 1.155 User's Guide