NHibernate: Как узнать, будет ли отправлен SQL при Flush()?

Я немного озадачен методом NHibernate IsDirty().

Непосредственно после получения (очень большого) сложного объекта из моей базы данных ISession.IsDirty() NHibernate дает «истину».

IFacadeDAL fd = new FacadeDAL();
// Session's not dirty

IProject proj = fd.GetByID<IProject, string>("123611-3640");
// Session is dirty

Однако, если я вызову Commit() следующим образом:

using (ITransaction trans = Facade.Session.Transaction)
{
    trans.Begin();
    Facade.Session.Save(entity);
    trans.Commit();
    return true;
}

это приводит к отсутствию sql (за исключением «exec sp_reset_connection»).

Я читал, что из-за «выбора сопоставления» вы можете получить «призраков» в своем сеансе (заставляя сеанс говорить, что он грязный), но не будет ли он также пытаться что-то обновить? Кроме того, если это вызвано, например. "преобразовав" бит sql в логическое значение С#, я не думаю, что смогу его изменить... (но не знаю, может ли это быть причиной призраков).

Обновление 2: здесь задействовано несколько представлений (sql server) и таблиц. Это (очень) упрощенный класс:

public class Project : IProject
{
    private string id;
    private List<IPlantItem> plantItems;

    public Project() { }

    public virtual string ID
    {
        get { return id; }
    }

    public virtual IEnumerable<IPlantItem> PlantItems
    {
        get { return plantItems; }
    }
}

'PlantItem сохраняется в таблице. Поэтому я ожидаю, что когда я что-то изменю в PlantItem, IsDirty должен измениться на «true».

Мой вопрос: есть ли способ проверить, будет ли сессия в этот момент на flush() (или, в моем случае, на commit()) генерировать фактические операторы sql? И если нет: есть ли другой способ (вручную) сохранить какой-то снимок сеанса для сравнения с текущим сеансом?

Обновление 1: я должен также упомянуть следующие аспекты:

  1. что для моего FlushMode установлено значение «Нет».
  2. что базовые данные самого объекта «IProject» основаны на sql-представлении и, следовательно, имеют большинство свойств в сопоставлении, установленном на update = «false»
  3. что, когда я действительно что-то меняю в объекте и использую тот же метод для сохранения, отправляются операторы обновления sql (и, таким образом, все фиксируется просто отлично)

person Hadzjie    schedule 14.05.2014    source источник
comment
Просто чтобы убедиться: ваш FlushMode установлен на NONE? и если это так: почему вы не звоните session.Flush() перед trans.Commit()? None означает, что Flush никогда не будет коллирован. Никогда, ни на коммит.   -  person Radim Köhler    schedule 14.05.2014
comment
@Radim: Спасибо, Радим, но в этом случае я использую nh ITransaction, поэтому в соответствии с этим: nhforge.org/doc/nh/en/index.html#manipulatingdata-endingsession , мне бы не пришлось. Кроме того, все остальные функции работают нормально (фиксация изменений и прочее).   -  person Hadzjie    schedule 14.05.2014
comment
Может быть, у вас есть призрачное сопоставление, которое заставляет сеанс думать, что оно грязное, но, поскольку оно отображается как update="false", никакие обновления не отправляются?   -  person dotjoe    schedule 14.05.2014
comment
Грязный хак, чтобы остановить любые обновления представления (я подозреваю, что у вас есть призрак), состоит в том, чтобы добавить <class name="Foo" table="foo_table" mutable="false"> к вашим сопоставлениям классов.   -  person Rippo    schedule 14.05.2014
comment
Почему установка mutable на false является грязным взломом? Я бы посоветовал посмотреть тест охотника за привидениями и включить его в свой тестовый костюм. joseoncode.com/2010/02/05/nhibernate-ghostbuster -версия-1-1   -  person Fran    schedule 15.05.2014
comment
Да, слово «хак» немного вырвано из контекста, если вы не можете найти проблему, то это будет взлом. Если вы можете найти проблему серьезной, включите mutable=false на этом этапе, это не будет взломом. В любом случае установить mutable=false для отображений представлений — хорошая идея. Эта ссылка также может помочь вам определить, есть ли у вас призрак nhforge.org/blogs/nhibernate/archive/2008/10/20/   -  person Rippo    schedule 15.05.2014
comment
Проблема не в «представлении» (я обновлю вопрос). Я хочу различать: будет отправлено sql, а не будет быть sql (отправить).   -  person Hadzjie    schedule 15.05.2014
comment
@Rippo Я почти уверен, что есть «призраки» .. Надеялся, что не нужно будет проходить сопоставления +60 одно за другим ... Однако предложенное вами решение (Охотник за привидениями) выглядит многообещающе! Я проверю это   -  person Hadzjie    schedule 15.05.2014
comment
А, я вижу таблицы и представления :). По моему опыту, призраки могут быть вызваны тем, что база данных является целым числом, допускающим значение NULL, а сопоставление — обычным целым числом. Когда объект гидратируется, обнуляемый db int преобразуется в ноль и, следовательно, теперь он грязный. Или указав неправильный тип в отображении XML. Удачи!   -  person Rippo    schedule 15.05.2014
comment
@Rippo С моей версией VS я не могу заставить этот код работать (для этого нужно пространство имен VisualStudio, а для этого, в свою очередь, требуется VS201x Premium или выше; я использую VS2013 Prof.). Ясно, однако, что мне придется пройти через свои сопоставления. Почему бы вам не написать свой комментарий как «Ответ», чтобы я мог отметить его?   -  person Hadzjie    schedule 15.05.2014


Ответы (2)


По моему опыту, призраки могут быть вызваны тем, что база данных является nullable int, а сопоставление — обычным int.

Когда объект увлажняется, nullable db int преобразуется в zero и, следовательно, становится грязным.

Другой способ получить грязные записи — указать неправильный тип в отображении XML, например.

public enum Sex
{
 Unspecified,
 Male,
 Female
}
...
public virtual Sex Sex { get; set; }

и укажите int в отображении.

 <property name="Sex" type="int"/>

См. эту ссылку для тестирования ваши сопоставления, которые объясняют более подробно.

person Rippo    schedule 15.05.2014

Если некоторые из ваших сущностей грязные - и, следовательно, ISession грязная - у вас есть несоответствие между свойствами и базой данных. Например, представьте, что у вас есть столбец в таблице, который может принимать значения NULL, но в вашем коде он установлен как не нулевой (например, int). NHibernate посчитает его грязным, потому что его текущее значение (0 в случае целого числа) отличается от значения, пришедшего из БД (null). Найдите в Google «Призрачные свойства NHibernate».

person Ricardo Peres    schedule 15.05.2014