2010-08-26 3 views
2

Après la mise à niveau vers DNN 5.5.0, nous avons dû mettre en œuvre IHydratable sur tous nos objets de gestion.Comment implémenter correctement l'interface IHydratable dans DNN?

Cette idée m'a semblé être un bon début, mais après avoir joué avec IHydratable je n'en suis plus si sûr.

Il y a deux possibilités:

  1. Je le fais mal
  2. IHydratable forces vous d'utiliser select * construire une toutes vos requêtes

L'étude de cas:

  • Ma première sproc retourne le BgId et BgShortDesc
  • Ma deuxième retourne sproc BgId et BgReportedUser

Mon IHydratable est mis en œuvre comme indiqué ci-dessous:

public class Bug : IHydratable 
{ 
    public int BgId { get; set; } 
    public string BgShortDesc { get; set; } 
    public int BgReportedUser { get; set; } 
    public DateTime BgReportedDate { get; set; } 

    public Bug() { } 

    public int KeyID 
    { 
    get { return BgId; } 
    set { BgId = value; } 
    } 

    public void Fill(IDataReader dr) 
    { 
    BgId = Convert.ToInt32(Null.SetNull(dr["BgId"], BgId)); 
    BgShortDesc = Convert.ToString(Null.SetNull(dr["BgShortDesc"], BgShortDesc)); 
    BgReportedUser = Convert.ToInt32(Null.SetNull(dr["BgReportedUser"], BgReportedUser)); 
    BgReportedDate = Convert.ToDateTime(Null.SetNull(dr["BgReportedDate"], BgReportedDate)); 
    } 
} 

La méthode de remplissage va jeter un IndexOutOfRangeException sur l'un des sprocs ci-dessus, car tous les champs ne sont pas retournés avec IDataReader.

Le moyen le plus simple de contourner le problème est d'utiliser select * dans tous les sprocs, mais ce n'est pas une bonne pratique.

Quelle est la bonne façon d'implémenter IHydratable dans ce scénario?

P.S. Gardez à l'esprit que mon exemple est trop simplifié pour faire passer le message.

Répondre

1

avoir obtenu une réponse possible à ce sur another forum

est ici la suggestion:

public void Fill(IDataReader dr) 
    { 
      if (dr.ColumnExists("BgId")) 
      { 
       BgId = Convert.ToInt32(Null.SetNull(dr["BgId"], BgId)); 
      } 
      //do the above for all the properties 
    } 

EDIT:

trouvé une meilleure façon de le faire en écrivant une méthode d'extension sur IDataReader avec l'aide de ces 2 réponses sur SO (@JamesEggers et @Chad Grant)

/// <summary> 
    /// Check if the column exists in the datareader before accessing its value 
    /// </summary> 
    /// <param name="reader">DataReader</param> 
    /// <param name="columnName">Column name</param> 
    /// <returns>True if column exists, false if not</returns> 
    public static bool ColumnExists(this IDataReader reader, string columnName) 
    { 
     for (int i = 0; i < reader.FieldCount; i++) 
     { 
      if (reader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase)) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 
Questions connexes