IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

problème de conversion avec un DateTime valant null dans une requête LINQ


Sujet :

C#

  1. #1
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut problème de conversion avec un DateTime valant null dans une requête LINQ
    Bonjour, j'ai mis ce sujet dans c# au début, mais il a plus sa place ici (je ne sais pas comment changer de lieu un sujet dans le forum, donc je crée un nouveau sujet, désolé les modérateurs...)

    Bonjour,
    Voici la configuration de mes datatables que j'utilise dans ma requête linq:
    J'ai 2 fichiers dataset ( toutes les colonnes de toutes les tables ont un datatype de spécifié et leur propriété AllowDbNull vaut True):
    * deposit_position_imbalance.xsd:
    Contient 2 datatables : - "Imbalance"
    - "ImbalanceDetailForRealTime"
    * dep_pos_imbalance_detail.xsd:
    Contient 1 datatable : - "Table"

    Dans le code ci-dessous, le problème se situe dans les 2 lignes "deal_date = b.deal_date".
    En effet, quand la base de donnée me retourne un b.deal_date qui a une valeur null, ça dit dans deposit_position_imbalance.Designer.cs :
    "StrongTypingException was unhandled by user code"
    "The value for column 'deal_date' in table 'ImbalanceDetailForRealTime' is DBNull."
    "Specified cast is not valid".
    Voici où l'erreur surgit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
            public System.DateTime deal_date {
                get {
                    try {
                        return ((global::System.DateTime)(this[this.tableImbalanceDetailForRealTime.deal_dateColumn]));
                    }
                    catch (global::System.InvalidCastException e) {
                        throw new global::System.Data.StrongTypingException("The value for column \'deal_date\' in table \'ImbalanceDetailForRealTime\' is DBNull." +
                                "", e);//L'ERREUR SURGIT ICI
                    }
                }
                set {
                    this[this.tableImbalanceDetailForRealTime.deal_dateColumn] = value;
                }
            }
    * J'ai essayé de remplacer la ligne "deal_date = b.deal_date" par
    "deal_date = (DateTime?)b.deal_date"
    Mais j'ai 2 erreurs de compilation: "The best overloaded method match for dep_pos_imbalance_detail.TableDataTable.AddTableRow(string, System.DateTime)' has some invalid arguments"
    et "Argument '2': cannot convert from 'System.DateTime?' to 'System.DateTime'"
    * J'ai aussi essayé de remplacer la ligne "deal_date = b.deal_date" par
    "deal_date = b.deal_date == null ? (DateTime)DBNull.Value : b.deal_date"
    Mais j'ai 1 erreur de compilation: "Cannot convert type 'System.DBNull' to System.DateTime'"
    * J'ai enfin essayé de remplacer la ligne "deal_date = b.deal_date" par
    "deal_date = b.deal_date == null ? (DateTime?)DBNull.Value : b.deal_date"
    Mais j'ai 1 erreur de compilation: "Cannot convert type 'System.DBNull' to System.DateTime?'"
    * J'ai aussi essayer de remplacer "deal_date = b.deal_date"
    par "deal_date = b.Isdeal_dateNull() ? default(DateTime?) : b.deal_date"
    Et je me retrouve avec les erreurs:
    "The best overloaded method match for dep_pos_imbalance_detail.TableDataTable.AddTableRow(string, System.DateTime)' has some invalid arguments"
    et "Argument '2': cannot convert from 'System.DateTime?' to 'System.DateTime'"
    J'ai mis en copie un imprim écran de la définition de ma colonne deal_date pour que l'on puisse me dire s'il y a quelque chose à modifier éventuellement.
    On peut voir que je n'ai pas a priori la possibilité de mettre "System.DateTime?" mais seulement "System.DateTime". Et je ne veux pas autre chose que null comme valeur par défaut (est-ce qu'il faut mettre autre chose que la valeur par défaut "<DBNull>" pour que ça marche?)
    UPDATE--> J'ai essayé de mettre null à la place de <DBNull> et le designer met l'erreur : "The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.".
    Quand j'essaye aussi de modifier la propriété NullValue pour la faire passer de "(Throw Exception)" à "(Empty)" ou "(Null)", le designer me donne l'erreur "The value entered is not valid for the current data type."

    Donc, je ne comprends pas comment gérer la réception de valeurs null (je ne l'ai pas mis dans le code mais j'ai le même problème avec le type double). J'ai l'impression que mes colonnes sont paramétrées pour permettre les valeurs null mais visiblement non...
    Merci beaucoup pour votre aide.
    Voici ma requête LINQ:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    deposit_position_imbalance.ImbalanceDataTable dtImbalanceForRealTime;
    deposit_position_imbalance.ImbalanceDetailForRealTimeDataTable dtImbalanceDetailForRealTime;
     
    dtImbalanceForRealTime = (deposit_position_imbalance.ImbalanceDataTable)(((deposit_position_imbalance)(dataManager.GetConfig(grid1).ParentDataSource)).Imbalance);
    dtImbalanceDetailForRealTime = this.detailForRealTime;
     
    // we separate security_id null and not null
    // Security id is not null
    deposit_position_imbalance.ImbalanceDataTable iWithSecurityIdNotNull = new deposit_position_imbalance.ImbalanceDataTable();
    deposit_position_imbalance.ImbalanceRow[] dr1 = (deposit_position_imbalance.ImbalanceRow[])dtImbalanceForRealTime.Select("security_id is not null");
    if (dr1.Count<deposit_position_imbalance.ImbalanceRow>() > 0)
    {
        DataTable looselyTypedDT1 = dr1.CopyToDataTable<deposit_position_imbalance.ImbalanceRow>();
        iWithSecurityIdNotNull.Merge(looselyTypedDT1, true);
    }
     
    // Security id is null
    deposit_position_imbalance.ImbalanceDataTable iWithSecurityIdNull = new deposit_position_imbalance.ImbalanceDataTable();
    deposit_position_imbalance.ImbalanceRow[] dr2 = (deposit_position_imbalance.ImbalanceRow[])dtImbalanceForRealTime.Select("security_id is null");
    if (dr2.Count<deposit_position_imbalance.ImbalanceRow>() > 0)
    {
        DataTable looselyTypedDT2 = dr2.CopyToDataTable<deposit_position_imbalance.ImbalanceRow>();
        iWithSecurityIdNull.Merge(looselyTypedDT2, true);
    }
     
    var queryWithSecurityIdFound =
        from a in iWithSecurityIdNotNull
        join b in dtImbalanceDetailForRealTime
        on new
        {
            a.situation_date,
            a.security_id,
            a.deposit_location_id,
            a.account_keeper_id
        }
            equals new
            {
                b.situation_date,
                b.security_id,
                b.deposit_location_id,
                b.account_keeper_id
            }
        where a.situation_date == situation_date
           && a.security_id == security_id
           && a.deposit_location_id == deposit_location_id
           && a.account_keeper_id == account_keeper_id
        select new
        {
            name = a.bo_source_name,
            deal_date = b.deal_date
        };
     
    var queryWithSecurityIdNotFound =
        from a in iWithSecurityIdNull
        join b in dtImbalanceDetailForRealTime
            on new
            {
                a.situation_date,
                a.security_code,
                a.deposit_location_id,
                a.account_keeper_id
            }
            equals new
            {
                b.situation_date,
                b.security_code,
                b.deposit_location_id,
                b.account_keeper_id
            }
        where a.situation_date == situation_date
           && a.security_id == security_id
           && a.deposit_location_id == deposit_location_id
           && a.account_keeper_id == account_keeper_id
        select new
        {
            name = a.bo_source_name,
            deal_date = b.deal_date
        };
     
    var query_final = queryWithSecurityIdFound.Union(queryWithSecurityIdNotFound);
    //We fill the 'dep_pos_imbalance_detail Table'
    grid1.Clear();
    foreach (var item in query_final)
    {
        ((dep_pos_imbalance_detail.TableDataTable)grid1.DataSet.Tables["Table"]).AddTableRow(item.name, item.deal_date);
    }
    Images attachées Images attachées  

  2. #2
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut
    DateTime et double sont des types valeurs, et donc si tu veux pouvoir leur attribuer "null", il faut que tu passes par Nullable<T>.

    Il te suffit pour ça de déclarer ton objet deal_date en DateTime? (ou double? pour ton autre cas)

  3. #3
    Membre Expert Avatar de sisqo60
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2006
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 754
    Par défaut
    Bonjour,

    En plus de ce que t'as dit Er3van, tu y étais presque quand tu as écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    deal_date = b.deal_date == null ? (DateTime)DBNull.Value : b.deal_date
    c'est l'inverse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    deal_date = b.deal_date == DBNull.Value ? null : b.deal_date
    Surtout deal_date doit être un Nullable<DateTime> (ou DateTime? (c'est équivalent))

    Bon dév.

  4. #4
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut
    Bonjour,
    Merci pour la réponse, mais c'est justement ça mon problème, je ne sais pas comment déclarer mon deal_date à nullable on dirait, je m'explique:
    Je passe par le DataSet Editor de Visual Studio, à l'intérieur duquel j'ai créé mes tables, et dans les définitions de mes colonnes, je paramètre la propriété DataType à System.DateTime et la propriété AllowDbNull à True. Je ne peux pas explicitement mettre "Datetime?" comme DataType, où en tout cas je ne sais pas faire, et je veux bien que vous me disiez comment justement.
    Merci bien.

  5. #5
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut
    Citation Envoyé par sisqo60 Voir le message
    Bonjour,

    En plus de ce que t'as dit Er3van, tu y étais presque quand tu as écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    deal_date = b.deal_date == null ? (DateTime)DBNull.Value : b.deal_date
    c'est l'inverse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    deal_date = b.deal_date == DBNull.Value ? null : b.deal_date
    Surtout deal_date doit être un Nullable<DateTime> (ou DateTime? (c'est équivalent))

    Bon dév.
    J'ai fait ce que tu as dit, et là j'ai les messages d'erreur suivants:
    "Cannot assign <null> to anonymous type property"
    "Operator '==' cannot be applied to operands of type 'System.DateTime' and 'System.DBNull'"

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Il faut vérifier si la colonne deal_date est nulle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        ...
        select new
        {
            name = a.bo_source_name,
            deal_date = b.IsNull("deal_date") ? default(DateTime?) : b.deal_date)
        };
    (j'utilise default(DateTime?) plutôt que null, sinon le compilateur ne sait pas quoi choisir comme type de retour de l'opérateur conditionnel)

    Vu que c'est un dataset fortement typé, il y a sans doute une méthode IsDeal_dateNull ou quelque chose comme ça, que tu peux utiliser à la place de IsNull("deal_date")

  7. #7
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut
    Malheureusement, ça ne fonctionne pas.
    J'ai bien remplacé "deal_date = b.deal_date"
    par "deal_date = b.Isdeal_dateNull() ? default(DateTime?) : b.deal_date"
    Et je me retrouve avec les erreurs:
    "The best overloaded method match for dep_pos_imbalance_detail.TableDataTable.AddTableRow(string, System.DateTime)' has some invalid arguments"
    et "Argument '2': cannot convert from 'System.DateTime?' to 'System.DateTime'"
    J'ai mis en copie un imprim écran de la définition de ma colonne deal_date pour que l'on puisse me dire s'il y a quelque chose à modifier éventuellement.
    On peut voir que je n'ai pas a priori la possibilité de mettre "System.DateTime?" mais seulement "System.DateTime". Et je ne veux pas autre chose que null comme valeur par défaut (est-ce qu'il faut mettre autre chose que la valeur par défaut "<DBNull>" pour que ça marche?)
    UPDATE--> J'ai essayé de mettre null à la place de <DBNull> et le designer met l'erreur : "The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.".

    Citation Envoyé par tomlev Voir le message
    Il faut vérifier si la colonne deal_date est nulle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        ...
        select new
        {
            name = a.bo_source_name,
            deal_date = b.IsNull("deal_date") ? default(DateTime?) : b.deal_date)
        };
    (j'utilise default(DateTime?) plutôt que null, sinon le compilateur ne sait pas quoi choisir comme type de retour de l'opérateur conditionnel)

    Vu que c'est un dataset fortement typé, il y a sans doute une méthode IsDeal_dateNull ou quelque chose comme ça, que tu peux utiliser à la place de IsNull("deal_date")
    Images attachées Images attachées  

  8. #8
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut
    Quand j'essaye aussi de modifier la propriété NullValue pour la faire passer de "(Throw Exception)" à "(Empty)" ou "(Null)", le designer me donne l'erreur "The value entered is not valid for the current data type."

  9. #9
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut
    J'ai trouvé une manière de résoudre mon problème:
    Dans mes requêtes linq, je remplace "deal_date = b.deal_date" par "deal_date = b.Field<DateTime?>('deal_date')"
    La conversion arrive du coup à se faire. Je ne peux donc ensuite pas passer par la méthode générée par le designer "AddTableRow" car elle n'attends pas les bons types. Mais j'écris ceci, un peu plus long mais fonctionne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    dep_pos_imbalance_detail.TableDataTable dt = ((dep_pos_imbalance_detail.TableDataTable)grid1.DataSet.Tables["Table"]);
    dep_pos_imbalance_detail.TableRow dr = dt.NewTableRow();
    foreach (var item in query_final)
    {
        dr = dt.NewTableRow();
        dr.name = item.name;
        if (item.deal_date.HasValue)
            dr.deal_date = (DateTime)item.deal_date;
        else
            dr.Setdeal_dateNull();
        dt.AddTableRow(dr);
    }

  10. #10
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut
    Plutôt que de caster, tu peux écrire ceci :

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    dr.deal_date = item.deal_date.Value;

  11. #11
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut
    Effectivement, c'est plus propre.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. probleme avec un champ null dans une requête sql
    Par kroma23 dans le forum Bases de données
    Réponses: 6
    Dernier message: 20/03/2014, 15h09
  2. Réponses: 5
    Dernier message: 28/04/2008, 14h48
  3. Pbs de date nulle dans une requête ACCESS
    Par tedparker dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 24/07/2006, 22h39
  4. Comment gérer les valeur Nulles dans une requête ?
    Par sondo dans le forum Bases de données
    Réponses: 3
    Dernier message: 16/03/2005, 11h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo