Как правильно реализовать интерфейс IHydratable в DNN? - PullRequest
2 голосов
/ 27 августа 2010

После обновления до DNN 5.5.0 нам пришлось реализовать IHydratable на всех наших бизнес-объектах.

Поначалу эта идея казалась хорошим вариантом, но после игры с IHydratable я уже не уверен.

Есть две возможности:

  1. Я делаю это неправильно
  2. IHydratable заставляет вас использовать select * построить все ваши запросы

Бизнес-кейс:

  • Мой первый sproc возвращает BgId и BgShortDesc
  • Мой второй sproc возвращает BgId и BgReportedUser

My IHydratable реализовано, как показано ниже:

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));
  }
}

Метод fill выдаст IndexOutOfRangeException для любого из вышеперечисленных sprocs, поскольку не все поля возвращаются с IDataReader.

Самый простой способ решить эту проблему - использовать select * во всех sprocs, но это не очень хорошая практика.

Какой правильный способ реализации IHydratable в этом сценарии?

P.S. Имейте в виду, что мой пример упрощен, чтобы объяснить суть.

1 Ответ

1 голос
/ 29 октября 2010

Я получил ответ на этот вопрос на другом форуме

Вот предложение:

    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:

Нашел лучший способ сделать это, написав метод расширения для IDataReader с помощью этих двух ответов на SO ( @ JamesEggers и @ 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;
    }
...