Problème MySqlParameter c#

Problème MySqlParameter c# - C#/.NET managed - Programmation

Marsh Posté le 30-10-2008 à 11:22:48    

Bonjour,
 
Voila j'ai crée une classe généric appelé Object qui est censé pouvoir charger/sauvegarder/modifier n'importe lequel de mes objets metiers.
Chaqu'un de mes objets metiers sont hérité d'une classe générique appelé Table, ils possède en plus un attribut qui définit le nom de la table et la clé primaire de la table en base. Chacune des propriétés possèdent un attribut correspodant au nom et au type du champ en base.
Ca c'est pour le contexte. Mon problème se situe au niveau de la sauvegarde. A chaque fois que je veux sauvegarder un object, je boucle sur les attribut et je récupère le nom du champs et la valeur associé, je construit ma requête comme ca.
La structure de la requête est correct mais les valuers ne sont pas remplacé. Par exemple pour une requête du type insert il me mettra :  
INSERT INTO test (id, value) values (@ID, @value). Il ne remplace pas les identifiants des paramètres par leurs valeurs.
Voici mon code, j'éspère avoir été assez clair :
 
 public static void SaveObject(AGDDataTable poObject)
        {
            MySqlConnection cn;
            MySqlParameter param;
            MySqlCommand cmd;
            String sSqlUpdate;
            String sSqlInsertFields;
            String sSqlInsertValues;
 
            Type type = poObject.GetType();
 
            AGDTable atrTable = ((AGDTable[])type.GetCustomAttributes(typeof(AGDTable), true))[0];
            String sTableName = atrTable.TableName;
            String sPrimaryKey = atrTable.PrimaryKey;
            String sVirgule = "";
 
            sSqlUpdate = "UPDATE " + sTableName + " SET ";
 
            sSqlInsertFields = "INSERT INTO " + sTableName + "(" + sPrimaryKey;
            sSqlInsertValues = " VALUES(@ID";
 
            foreach (PropertyInfo pi in type.GetProperties())//Construction de la requête à partir des propriétés de ma classe
            {
                AGDField[] aoField = (AGDField[])pi.GetCustomAttributes(typeof(AGDField), false);
                if (aoField.Length > 0)
                {
                    String sFieldName = aoField[0].FieldName;
 
                    sSqlUpdate += sVirgule + sFieldName + " = @" + sFieldName;
                    sSqlInsertFields += ", " + sFieldName;
                    sSqlInsertValues += ", @" + sFieldName;
 
                    sVirgule = ", ";
                }
            }
 
            sSqlUpdate += " WHERE " + sPrimaryKey + " = @ID";
            sSqlInsertFields += " )";
            sSqlInsertValues += " )";
 
            cn = new MySqlConnection(Properties.Resources.SECUConnectionString);
            cn.Open();
 
            if (poObject.Id > 0)
            {
                cmd = new MySqlCommand(sSqlUpdate, cn);
            }
            else
            {
                poObject.Id = GetNextId(sTableName);
 
                cmd = new MySqlCommand(sSqlInsertFields + sSqlInsertValues, cn);
            }
 
            foreach (PropertyInfo pi in type.GetProperties())//Création des parametres  
            {
                AGDField[] aoField = (AGDField[])pi.GetCustomAttributes(typeof(AGDField), false);
                if (aoField.Length > 0)
                {
                    //Récupère l'attribut AGDField permettant de savoir le nom du champ et le type en base
                    AGDField field = aoField[0];
                    param = new MySqlParameter(field.FieldName, field.DBType);
 
                    //Récupère la valeur de cette propriété pour cette instance d'objet
                    param.Value = pi.GetValue(poObject, null);
                    cmd.Parameters.Add(param);
                }
            }
 
            param = new MySqlParameter(sPrimaryKey, MySqlDbType.Int64);
            param.Value = poObject.Id;
            cmd.Parameters.Add(param);
 
            try
            {
                cmd.ExecuteNonQuery();
            }
            catch (Exception excp)
            {
                Exception myExcp = new Exception("Could not Save " + poObject.GetType().Name + ". Error: " +
                    excp.Message, excp);
                throw (myExcp);
            }
 
        }
 
Voila si quelqu'un sait pourquoi mes paramètres sont mal pris en compte je suis tout ouie :)

Reply

Marsh Posté le 30-10-2008 à 11:22:48   

Reply

Marsh Posté le 30-10-2008 à 11:35:29    

tu fais un peu n'importe quoi toi hein... [:shakalagoons]

 

1) créer une classe qui s'appelle Object c'est dangereux, car il existe déjà une classe Object dans l'arborescence de classes .NET, dont héritent toutes les classes

 

2) pour tes paramètres pas pris en compte, je sais pas ce que t'essaies de faire avec tes concaténations de chaines là, mais ça rime à rien. pourquoi ne pas faire un truc genre

Code :
  1. String req= "INSERT INTO Table(champ1, champ2) VALUES(?field1, ?field2);
  2. MySqlCommand cmd = new MySqlCommand(connection, req);
  3. cmd.Parameters.Add("?field1", valeur);
  4. cmd.Parameters.Add("?field2", valeur);
  5. cmd.ExecuteNonQuery();
  6. ...


au lieu de ton foreach bien cracra ?


Message édité par Harkonnen le 30-10-2008 à 11:36:50

---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 30-10-2008 à 11:41:43    

Pour la premiere remarque, elle ne s'appelle pas Object tout cours mal DALObject, j'ai dit object pour montrer qu'elle était générique (dsl de l'ambiguité).
Ensuite je ne connais ni les champs ni les valeurs lorsque j'appelle cette fonction.
Elle recoit un object de type AGDDataTable qui peut représenter n'importe qu'elle classe metier de mon application.
D'ou l'utilité de ma boucle foreach qui me sert à récupérer les champs et les valeurs je te mets en exemple une d mes classes metiers :
[AGDTable("SESSION", "ID_SESSION" )]
    public class Session : AGDDataTable
    {
        [AGDField("ID_LOGIN", AGDDBType.BigInt, typeof(Login))]
        public Login Login { get; set; }
 
        [AGDField("ID_BD", AGDDBType.BigInt, typeof(BD))]
        public BD BD { get; set; }
 
        [AGDField("DATEHDEBUT_SESSION", AGDDBType.BigInt)]
        public Int64 DateDebut { get; set; }
 
        [AGDField("DATEHFIN_SESSION", AGDDBType.BigInt)]
        public Int64 DateFin { get; set; }
 
        [AGDField("IP_SESSION", AGDDBType.Char)]
        public String Ip { get; set; }
 
        [AGDField("DTAEHMANIF_SESSION", AGDDBType.BigInt)]
        public Int64 DateManif { get; set; }
 
        [AGDField("ID_DATETRAITEMENT", AGDDBType.BigInt)]
        public Int64 DateTraitement { get; set; }
         
        [AGDField("CONTEXT_SESSION", AGDDBType.Blob)]
        public String Context { get; set; }
    }
Comme tu peux le voir la classe comme les propriétés ont un attribut, qui me permet de faire la liaison avec la table en base.
 
Tu vois ce que j'éssai de faire ou je suis vrement pas clair?

Reply

Marsh Posté le 30-10-2008 à 15:55:05    

Personne n'a une petite idée?

Reply

Marsh Posté le 30-10-2008 à 16:24:59    

tu utilises un ORM ?


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 30-10-2008 à 16:31:31    

Non je n'utilise pas d'ORM.
Tu penses que ce serait plus simple?

Reply

Marsh Posté le 30-10-2008 à 16:34:15    

Non mais je me demandais la provenance des metadata en entête de tes méthodes...


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 30-10-2008 à 16:37:47    

Ah,  ce sont des classes généric que j'ai crée.
En fait leur but est de faire une sorte de correspondance entre mes objets metiers et ma base de données

Reply

Marsh Posté le 30-10-2008 à 16:43:02    

En fait j'ai un peu plus approfondie mes recherches sur mon bug.
Il s'avère que ma requête se génère correctement, mes paramètre aussi.
Le pire c'est que en mode pas à pas une requète de mise à jours s'éxécute bien! Mais elle ne met pas a jour mon info! Malgré le fait que mon objet ai été modifié.
C'est la que je comprend plus
Mes paramètres contiennent bien les données modifié, ma requète s'éxécute mais pas de changement en base! tu vois?

Reply

Marsh Posté le 31-10-2008 à 13:58:53    

un commit manquant peut être?


---------------
quand un homme raisonne mal c'est qu'il n'a pas les données pour raisonner mieux (diderot)
Reply

Marsh Posté le 31-10-2008 à 13:58:53   

Reply

Marsh Posté le 03-11-2008 à 08:55:54    

La methode executenonQuery a besoin d'un commit?
Je me renseigne

Reply

Marsh Posté le 03-11-2008 à 09:02:28    

Non j'ai tenter de le faire en transactionnel ca marche pas mieux.
 
Je suis en pleine déprime :)

Reply

Marsh Posté le 03-11-2008 à 11:28:17    

Ok c'est bon,
en fait à l'initialisation de mes paramètres, le constructeur de MySqlParameter ne comprenait pas que field.DBType était le type de mon champ il considérait que c'était sa valeur.
J'ai retranscrit mon DBType en MySqlDBType et ca marche.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed