Alexey Suvorov dev blog

Мой разработческий блог

Archive for Июнь 2013

NHibernate.StaleStateException и порядок следования в мапингах nHibernate

leave a comment »

Все примеры orm показывают как использовать их правильно, но в реальной жизни их зачастую используют неправильно по соображениям удобства или производительности. В основном проекте мы используем nHibernate и делаем это неправильно :).

Если в 2-х словах то есть контейнер, который содержит назовем их виджеты, еще у контейнера есть сущности которые позволяют управлять некоторыми параметрами целой группы виджетов.

nHibernate

Так как ни группа ни свойства заранее неизвестны, то в базе они хранятся как ассоциация состоящая из WidgetId и PropertyId (на схеме PropertyId пропущено т.к. несущественно). Вся проблема заключается в том, что при удалении контейнера нужно удалять все виджеты и все мапинги на них. Но т.к по соображениям удобства мапинг содержит только WidgetId а не сам виджет, то nHibernate ничего не знает про эту связь и логичным решением поддержания базы в консистентном состоянии видится внешний ключ из таблицы мапингов на таблицу виджетов. Но тут же возникает проблема при удалении самого контейнера. nHibernate как ответственный бухгалтер считает что он сам должен удалить все учтённые мапинги и выстреливает исключением NHibernate.StaleStateException: Unexpected row count: 0; expected: 1 если вдруг база данных самовольно сделала это за него.

Решение оказалось очень простым — порядок следования деклараций в hbm файле является значимым и помещение тега коллекции мапингов до тега коллекции виджетов спасает ситуацию.

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="..." 
                   namespace="..." 
                   xmlns="urn:nhibernate-mapping-2.2">
  <class name="Container">
    <id name="Id">
      <generator class="..." />
    </id>
    
   <set name="CommonParameters" table="CommonPropertyMapping" cascade="all-delete-orphan">
      <key column="ContainerId" not-null="true" />
      <one-to-many class="CommonProperty" />
   </set>
   <set name="Widgets" table="Widget" cascade="all-delete-orphan">
      <key column="ContainerId" not-null="false" />
      <one-to-many class="Widget"/>
   </set>
  </class>
</hibernate-mapping>

Немного криво? Полностью согласен! Но мы живем в реальном мире.

Written by alexeysuvorov

06.06.2013 at 7:21 дп

Опубликовано в .net, nHibernate

Tagged with

Не найден Microsoft.Office.Interop.Word

leave a comment »

У меня потерялся весь Interop. Потерялся очень странно, потому что я видел его в GAC в списке сборок, но физически на диске сборки отсутствовали. Переустановка офиса не помогла, не помогло и добавление Office tools for visual studio к сетапу студии потому что как оказалось отношения к interop это не имеет вообще.
Далее 3 шага, каждый из которых может привести к решению проблемы, упорядоченные по возрастанию кривизны решения:

  • Установить Microsoft Office 2010: Primary Interop Assemblies Redistributable скачав его отсюда
  • Если не помог инсталлер и сборки не появились в add reference в студии, то скачиваем lessmsi или аналогичную тулу которая умеет распотрошить msi. Открываем msi скаченный на предыдущем шаге и достав сборки инсталлируем их в gac вручную
  • Мне не помог и вариант #2 так что я просто сложил нужные сборки (office.dll и Microsoft.office.interop.word.dll) в директорию к своему скрипту

В общем и целом опыт очень неприятный.

Written by alexeysuvorov

06.06.2013 at 7:20 дп

Опубликовано в .net, Uncategorized

Tagged with