NHibernate.MappingException: не сохраняется для: XYZ

134

Теперь, прежде чем вы скажете это: я сделал Google, и мой hbm.xmlфайл является встроенным ресурсом.

Вот код, который я звоню:

ISession session = GetCurrentSession();
var returnObject =  session.Get<T>(Id);

Вот мой файл сопоставления для класса:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="HQData.Objects.SubCategory, HQData" table="SubCategory" lazy="true">
    <id name="ID" column="ID" unsaved-value="0">
      <generator class="identity" />
    </id>

    <property name="Name" column="Name" />
    <property name="NumberOfBuckets" column="NumberOfBuckets"  />
    <property name="SearchCriteriaOne" column="SearchCriteriaOne" />

    <bag name="_Businesses" cascade="all">
      <key column="SubCategoryId"/>
      <one-to-many 
         class="HQData.Objects.Business, HQData"/>
    </bag>

    <bag name="_Buckets" cascade="all">
      <key column="SubCategoryId"/>
      <one-to-many
         class="HQData.Objects.Bucket, HQData"/>
    </bag>

  </class>
</hibernate-mapping>

Кто-нибудь раньше сталкивался с этой проблемой?

Вот полное сообщение об ошибке:

MappingException: не сохраняется для: HQData.Objects.SubCategory] NHibernate.Impl.SessionFactoryImpl.GetEntityPersister (String entityName, Boolean throwIfNotFound)
 в c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionFactoryImpl.cs: 766 NHibernate.Impl.SessionFactoryImpl.GetEntityPersister (String entityName)
 в c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionFactoryImpl.cs: 752 NHibernate.Event.Default.DefaultLoadEventListener.OnLoad (событие LoadEvent, LoadType loadType)
 в c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Event \ Default \ DefaultLoadEventListener.cs: 37 NHibernate.Impl.SessionImpl.FireLoad (событие LoadEvent, LoadType loadType)
 в c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 2054 NHibernate.Impl.SessionImpl.Get (String entityName, Object id)
 в c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 1029 NHibernate.Impl.SessionImpl.Get (Тип entityClass, Object id)
 в c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 1020 NHibernate.Impl.SessionImpl.Get (идентификатор объекта)
 в c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 985 HQData.DataAccessUtils.NHibernateObjectHelper.LoadDataObject (Int32 Id)
 в C: \ Development \ HQChannelRepo \ HQ Channel Application \ HQChannel \ HQData \ DataAccessUtils \ NHibernateObjectHelper.cs: 42 HQWebsite.LocalSearch.get_subCategory ()
 в C: \ Development \ HQChannelRepo \ HQ Channel Application \ HQChannel \ HQWebsite \ LocalSearch.aspx.cs: 17 HQWebsite.LocalSearch.Page_Load (Отправитель объекта, EventArgs e)
 в C: \ Development \ HQChannelRepo \ HQ Channel Application \ HQChannel \ HQWebsite \ LocalSearch.aspx.cs: 27 System.Web.Util.CalliHelper.EventArgFunctionCaller (IntPtr fp, Объект o, Объект t, EventArgs e) +15 System.Web .Util.CalliEventHandlerDelegateProxy.Callback (Отправитель объекта, EventArgs e) +33 System.Web.UI.Control.OnLoad (EventArgs e) +99 System.Web.UI.Control.LoadRecursive () +47 System.Web.UI.Page .ProcessRequestMain (логическое значение includeStagesBeforeAsyncPoint, логическое значение includeStagesAfterAsyncPoint) +1436

Обновление , вот каково было решение для моего сценария: я изменил некоторый код и не добавлял сборку в файл конфигурации во время выполнения.

Сара Чиппс
источник
У меня была та же ошибка, но другая проблема. Session.Load ("SearchItem", searchItemID), поскольку SearchItem возвращает ошибку сопоставления, а Session.Load <SearchItem> (searchItemID) - нет (и в любом случае это менее подверженный ошибкам способ сделать это.
Кендрик

Ответы:

101

Похоже, вы забыли добавить сопоставление сборки в конфигурацию фабрики сеанса ..

Если вы используете app.config ...

.
.
    <property name="show_sql">true</property>
    <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
    <mapping assembly="Project.DomainModel"/>  <!-- Here -->
</session-factory>
.
.
Энди С
источник
7
Как сделать это в Fluent NHibernate, я разрабатываю шаблон в отдельном проекте, чтобы у меня не было доступа к пользовательской сборке?
Мустафа Мэгди
Если вы не можете сослаться на пользовательскую сборку, я не думаю, что вы сможете использовать Fluent NHibernate.
Энди С
91

Что-то очевидное, но весьма полезное для новичка в NHibernate.

Все файлы XML Mapping должны рассматриваться как встроенные ресурсы, а не как контент по умолчанию . Эта опция устанавливается путем редактирования атрибута Build Action в свойствах файла.

Затем XML-файлы встраиваются в сборку и анализируются при запуске проекта на этапе настройки NHibernate.

Крис Воснидис
источник
1
Аллилуйя, у меня есть это как Embedded resource, но когда я скопировал это с одного компьютера на другой, файл потерял это свойство. Я почесал голову на пару хороших минут.
Драгос Дурлут
1
@DragosDurlut файл проекта (.csproj), который сохраняет информацию о файлах проекта, а не сам файл.
Вагнер Леонарди
50

Моя проблема заключалась в том, что я забыл поставить .hbm в названии сопоставления xml. Также убедитесь, что вы делаете это встроенным ресурсом!

Пользователь nHibernate
источник
1
Это тоже была моя ошибка!
Гринго
Это было моей проблемой также, получить ту же ошибку, что и в Q при выполнении get. При попытке запросить все объекты этого типа, без ошибок, просто пустой набор результатов!
Кристоф
Arg - тоже забыл .hbm. Спасибо!
Доктор К. Илариус,
42

Я получил это отсюда :

В моем случае класс картирования не был публичным. Другими словами, вместо:

public class UserMap : ClassMap<user>  // note the public!

У меня только что был:

class UserMap : ClassMap<user>
basarat
источник
Спасибо, вы только что спасли меня от головной боли. :)
Ритмис
2
Если вы используете свободный, я бы сказал, что это будет более распространенной причиной. Спасибо, это было очень легко пропустить.
Ричард Нил Илаган
1
Спасибо! Собираясь проверить, обнародовал ли я свои классы отображения или нет, я обнаружил, что не написал класс отображения для этой сущности - упс !! :) сэкономил мне кучу времени !!
Джен
28

Потратив около 4 часов на поиск в Google и переполнение стека , пробуя все вокруг, я нашел свою ошибку:

Мой файл сопоставления назывался .nbm.xml вместо .hbm.xml . Это было безумно.

Nickmaovich
источник
9
Ага, просто сделал то же самое, за исключением того, что у меня было просто .xml вместо .hbm.xml. Может быть, в ошибках должны быть некоторые намеки :)
Rezler
2
О, мой бог. Я не могу поверить, что я сделал это. Я искал часы в файлах сопоставления для ошибок, и оказалось, что я сделал опечатку в имени файла ... doh. Спасибо! Мне страшно подумать, как долго я бы рвал на себе волосы, если бы не наткнулся на это.
Камуи
1
Вау, отличный улов - я выдернула волосы из-за этой проблемы. Просматривал мой xml-файл сто раз и не мог понять, почему он не работает, как другие. Я фактически пропустил ".hbm" часть имени файла. Спасибо!
Вингер
Вы сохранили мои часы. Спасибо
Manjay_TBAG
4

У меня была похожая проблема, и я решил ее следующим образом:

Я работал над MS SQL 2008, но в конфигурации NH у меня был плохой диалект: NHibernate.Dialect. MsSql2005Dialect, если я исправлю это: NHibernate.Dialect. MsSql2008Dialect, тогда все работает нормально, без исключения "Нет сохранения для: ..." Дэвид.

Дэвид
источник
3

Я также добавил неправильную сборку во время инициализации. Класс, который я сохраняю, находится в сборке # 1, а мой файл .hbm.xml встроен в сборку # 2. Я изменил, cfg.AddAssembly(...чтобы добавить сборку # 2 (вместо сборки # 1), и все работало. Спасибо!

Сет
источник
3

Чтобы добавить ответ Амола, не делайте ошибку, указав тип класса Interface. Убедитесь, что вы указали класс реализации . (Т.е. не используйте IDomainObjectType). Не то чтобы я сделал эту ошибку ... :)

goku_da_master
источник
2

Должно ли это быть name="Id"? Опечатки являются вероятной причиной.

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

Можете ли вы опубликовать все сообщение об ошибке?

Мэтт Хинце
источник
2

У меня была та же проблема, потому что я добавлял неправильную сборку в методе Configuration.AddAssembly ().

IdontCareAboutReputationPoints
источник
2

Эта ошибка возникает из-за неверной конфигурации сопоставления. Вы должны проверить, где вы установили .Mappings для своей фабрики сессий. В основном ищите ".Mappings (" в вашем проекте и убедитесь, что вы указали правильный класс сущности в строке ниже.

.Mappings(m => m.FluentMappings.AddFromAssemblyOf<YourEntityClassName>())
Аркадас Килич
источник
Спасибо приятель! Я сменил проект, в котором сидели мои сущности!
Веггит
1

Если вы выполняете тесты в хранилище из отдельной сборки, убедитесь, что ваш Hibernate.cfg.xml всегда настроен на вывод в каталоге bin указанной сборки. Это не произошло для нас, и мы получили вышеуказанную ошибку при определенных обстоятельствах.

Отказ от ответственности: Это может быть немного эзотерическим советом, учитывая, что это является прямым результатом того, как мы структурируем наши тестовые сборки интеграции репозитория (т. Е. У нас есть символическая ссылка из каждой тестовой сборки на один файл Hibernate.xfg.xml)


источник
1

Не забудьте указать информацию о сопоставлении в файле .config

например

где MyApp.Data - сборка, содержащая ваши сопоставления


источник
0

У меня была похожая проблема при поиске объекта по идентификатору ... Все, что я делал, это использовал полное имя в имени класса. То есть до этого было:

find("Class",id)

Объект так стал таким:

find("assemblyName.Class",id)
Джефф Этвуд
источник
0

Убедитесь, что вы вызвали CreateCriteria(typeof(DomainObjectType))метод в Session для объекта домена, который вы собираетесь извлечь из БД.

Amol
источник
Это настойчиво, а не надумано.
Джошуа Дрейк
0

У меня похожая проблема, но все указанные требования выполнены. В моем случае я пытаюсь сохранить некоторый класс сущностей (Тип OBJEKTE) обратно в БД. Другие места работают, но только в этом случае это терпит неудачу и вызывает это исключение.

Мое решение (HACK) состояло в том, чтобы повторно сопоставить объект типа OBJEKTE и затем сохранить его. Вдруг это работает. Но не спрашивай почему.

            OBJEKTE t = _mapper.Map<OBJEKTE>(inparam);
            OBJEKTE res = await _objRepo.UpdateAsync(t);

Если inparam идет прямо к UpdateAsync (), он не может найти соответствующий персистор.

Это можно объяснить тем, как это делает NH. Он получает прокси из вашего класса отображения и реализует свойства с включенной грязной обработкой. Посмотри это:

t.GetType()
{Name = "OBJEKTE" FullName = "MyComp.Persistence.OBJEKTE"}

inparam.GetType()
{Name = "OBJEKTEProxyForFieldInterceptor" FullName = "OBJEKTEProxyForFieldInterceptor"}

Самое интересное, что источником inparamявляется собственно хранилище NH. В любом случае. Я остаюсь с этим хаком переназначения в следующий раз.

Robetto
источник