Nhibernate - Инициализация списков - Лучшая практика? - PullRequest
6 голосов
/ 16 июня 2009

Мне было просто интересно узнать о CodeWarning (ConstructorsShouldNotCallBaseClassVirtualMethods) и о том, есть ли лучший способ сделать это. У меня есть простой класс сборщика журналов, и я использую NHibernate для извлечения некоторых объектов.

Иногда я сам создаю объекты (конечно) и добавляю их в NHibernate для настойчивости. Как лучше всего убедиться, что Списки никогда не равны NULL.

В настоящее время я делаю это, но это не кажется "идеальным". Есть идеи на эту тему?

public class LogRun
{
    public virtual int Id { get; private set; }
    public virtual DateTime StartTime { get; set; }
    public virtual DateTime EndTime { get; set; }
    public virtual IList<Log> LogMessages { get; set; }
    public virtual int LogMessageCount { get { return LogMessages.Count; } }

    public LogRun()
    {
        LogMessages = new List<Log>();
    }


}

Ответы [ 2 ]

8 голосов
/ 16 июня 2009

Является ли LogMessages постоянной вещью? Если так, то лучше никогда не подвергать публичного сеттера. NHibernate становится странным, если вы получаете из базы данных и затем заменяете этот IList новым:

var myLog = session.Get<LogRun>(1);
Assert.True(myLog.LogMessages.Count > 0);
myLog.LogMessages = new List<Log>();

Если вы заметили, NHibernate возвращает прокси-объект, а замена его на общий список приведет к тому, что он станет ненадежным при попытке сохранить обратно.

Как правило, я предпочитаю иметь закрытое поле, которое я инициализирую, а затем предоставляю клиенту только геттер:

public class LogRun
{
    private IList<Log> logMessages = new List<Log>();

    public virtual int Id { get; private set; } 
    public virtual DateTime StartTime { get; set; } 
    public virtual DateTime EndTime { get; set; }
    public virtual IList<Log> LogMessages { get { return logMessages; } } 
    public virtual int LogMessageCount { get { return LogMessages.Count; } }

    public void AddLogMessage(Log log)
    {
        logMessages.Add(log);
    }
}

На самом деле, я иду дальше, клиент получает IEnumerable <>, и я добавляю вспомогательную функцию для добавления.

Моя имплентация будет выглядеть как

public class LogRun
{
    private IList<Log> logMessages = new List<Log>();

    public virtual int Id { get; private set; } 
    public virtual DateTime StartTime { get; set; } 
    public virtual DateTime EndTime { get; set; }
    public virtual IEnumerable<Log> LogMessages { get { return logMessages; } } 
    public virtual int LogMessageCount { get { return LogMessages.Count(); } }

    public void AddLogMessage(Log log)
    {
        logMessages.Add(log);
    }
}
1 голос
/ 16 июня 2009

Я делаю то же самое, но мне также интересно, насколько велико влияние на производительность, поскольку NHibernate также создаст новый List <> для каждого вызова конструктора по умолчанию ..

Я думаю, что нам повезло, и что это сработает. Рассмотрим NHibernate, создающий загруженный ленивый список LogRun'ов (поэтому мы все равно помечаем все как виртуальные):

  1. NHibernate отразит над LogRun и создаст производный класс
  2. NHibernate создаст прокси-список класса, производного от LogRun
  3. -
  4. Когда вы загружаете этот прокси, он создает экземпляры некоторых из этих производных классов, однако сначала вызывается базовый конструктор - создается новый список <> - затем вызывается производный конструктор, вместо этого создается список прокси.

По сути, мы создали список, который никогда не будем использовать.

Рассмотрим альтернативы:

  • Сделайте конструктор защищенным, чтобы никто не вызывал его, и сделайте альтернативу. Например, статический LogRun.GetNew (); способ.
  • Разрешить доступ общего доступа к IList <> и создавать его самостоятельно при создании нового объекта.

Честно говоря, я думаю, что оба они очень грязные, и, так как я (довольно) уверен, что накладные расходы при создании нового пустого списка при каждом вызове конструктора ограничены, это то, что я лично придерживаюсь до сих пор. Ну, по крайней мере, пока мой профилировщик не скажет мне иначе: P

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...