NHibernate.MappingException: Nie ma problemu z: XYZ


134

Teraz, zanim to powiesz: zrobiłem Google i mój hbm.xmlplik jest zasobem osadzonym.

Oto kod, który dzwonię:

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

Oto mój plik mapowania dla klasy:

<?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>

Czy ktoś już biegał do tego problemu?

Oto pełny komunikat o błędzie:

MappingException: No persister for: HQData.Objects.SubCategory] NHibernate.Impl.SessionFactoryImpl.GetEntityPersister (String entityName, Boolean throwIfNotFound)
 in c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionFactoryImpl.cs: 766 NHibernate.Impl.SessionFactoryImpl.GetEntityPersister (String entityName)
 in c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionFactoryImpl.cs: 752 NHibernate.Event.Default.DefaultLoadEventListener.OnLoad (zdarzenie LoadEvent, LoadType loadType)
 w c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Event \ Default \ DefaultLoadEventListener.cs: 37 NHibernate.Impl.SessionImpl.FireLoad (zdarzenie LoadEvent, LoadType loadType)
 in c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 2054 NHibernate.Impl.SessionImpl.Get (String entityName, identyfikator obiektu)
 in c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 1029 NHibernate.Impl.SessionImpl.Get (wpisz entityClass, identyfikator obiektu)
 in c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 1020 NHibernate.Impl.SessionImpl.Get (identyfikator obiektu)
 w c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 985 HQData.DataAccessUtils.NHibernateObjectHelper.LoadDataObject (Int32 Id)
 w C: \ Development \ HQChannelRepo \ HQ Channel Application \ HQChannel \ HQData \ DataAccessUtils \ NHibernateObjectHelper.cs: 42 HQWebsite.LocalSearch.get_subCategory ()
 w C: \ Development \ HQChannelRepo \ HQ Channel Application \ HQChannel \ HQWebsite \ LocalSearch.aspx.cs: 17 HQWebsite.LocalSearch.Page_Load (Object sender, EventArgs e)
 w C: \ Development \ HQChannelRepo \ HQ Channel Application \ HQChannel \ HQWebsite \ LocalSearch.aspx.cs: 27 System.Web.Util.CalliHelper.EventArgFunctionCaller (IntPtr fp, Object o, Object t, EventArgs e) +15 System.Web .Util.CalliEventHandlerDelegateProxy.Callback (Object sender, EventArgs e) +33 System.Web.UI.Control.OnLoad (EventArgs e) +99 System.Web.UI.Control.LoadRecursive () +47 System.Web.UI.Page .ProcessRequestMain (Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1436

Aktualizacja , oto rozwiązanie dla mojego scenariusza: Zmieniłem kod i nie dodawałem Assembly do pliku konfiguracyjnego podczas działania.


Miałem ten sam błąd, ale inny problem. Session.Load ("SearchItem", searchItemID) ponieważ SearchItem zwraca błąd mapowania, Session.Load <SearchItem> (searchItemID) nie (i jest mniej podatnym na błędy sposobem zrobienia tego mimo wszystko.
Kendrick

Odpowiedzi:


101

Wygląda na to, że zapomniałeś dodać zestawu mapującego do konfiguracji fabryki sesji.

Jeśli używasz 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
Jak to zrobić w Fluent NHibernate, tworzę wzorzec w projekcie serperatowym, więc nie mam dostępu do zestawu użytkownika?
Mustafa Magdy,

Jeśli nie możesz odwołać się do zestawu użytkownika, nie sądzę, że będziesz w stanie użyć Fluent NHibernate.
Andy S

91

Coś oczywistego, ale całkiem przydatnego dla kogoś nowego w NHibernate.

Wszystkie pliki mapowania XML powinny być traktowane jako zasoby osadzone, a nie jako domyślna zawartość . Ta opcja jest ustawiana poprzez edycję atrybutu Build Action we właściwościach pliku.

Pliki XML są następnie osadzane w zestawie i analizowane podczas uruchamiania projektu podczas fazy konfiguracji NHibernate.


1
Haleluia, mam to jako plik Embedded resource, ale kiedy skopiowałem go z jednego komputera na drugi, plik stracił tę właściwość. Podrapałem się po głowie przez kilka dobrych minut.
Dragos Durlut

1
@DragosDurlut plik projektu (.csproj), który zapisuje informacje o plikach projektu, a nie sam plik.
Wagner Leonardi

50

Mój problem polegał na tym, że zapomniałem wstawić .hbm w nazwie mapowania xml. Upewnij się również, że jest to zasób osadzony!


1
To też był mój błąd!
Gringo,

To też był mój problem, otrzymałem ten sam błąd co w Q podczas wykonywania get. Przy próbie odpytywania wszystkich obiektów tego typu nie ma błędu, tylko pusty zestaw wyników!
Christoph

Arg - zapomniałem też o .hbm. Dzięki!
Dr. C. Hilarius

42

Mam to stąd :

W moim przypadku klasa mapowania nie była publiczna. Innymi słowy, zamiast:

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

Właśnie miałem:

class UserMap : ClassMap<user>

Dzięki, właśnie uratowałeś mnie od bólu głowy. :)
Rytmis

2
Jeśli używasz Fluent, powiedziałbym, że jest to najczęstsza przyczyna. Dzięki, bardzo łatwo było to przegapić.
Richard Neil Ilagan

1
Dzięki! Chcąc sprawdzić, czy upubliczniłem moje klasy mapowania, odkryłem, że nie napisałem klasy mapowania dla tej encji - ups !! :) Zaoszczędziło mi mnóstwo czasu !!
Jen,

28

Spędzeniu około 4 godzin na googlowania i stackoverflowing , próbując wszystkich rzeczy wokół tam, znalazłem mój błąd:

Mój plik mapowania nazywał się .nbm.xml zamiast .hbm.xml . To było szalone.


9
Argh, po prostu zrobiłem to samo, ale miałem go po prostu jako .xml zamiast .hbm.xml. Może w błędach powinny być jakieś wskazówki :)
Rezler

2
o mój Boże. Nie mogę uwierzyć, że to zrobiłem. Szukałem godzinami w mapowaniu plików pod kątem błędów i okazało się, że popełniłem literówkę w nazwie pliku ... doh. Dziękuję Ci! Drżę na myśl, jak długo rwałbym włosy z głowy, gdybym się na to nie natknął.
kamui

1
Wow, świetny chwyt - wyciągałam włosy z tego problemu. Przeglądałem mój plik xml sto razy i nie mogłem zrozumieć, dlaczego nie działa jak inne. W rzeczywistości brakowało mi części „.hbm” w nazwie pliku. Dzięki!
Skrzydłowy

Zaoszczędziłeś mi godziny. Dzięki
Manjay_TBAG

4

Miałem podobny problem i rozwiązałem go następująco:

Pracuję na MS SQL 2008, ale w konfiguracji NH miałem zły dialekt: NHibernate.Dialect. MsSql2005Wybierz, jeśli poprawię to: NHibernate.Dialect. MsSql2008Wybierz, a następnie wszystko działa dobrze bez wyjątku „Nie ma problemu z: ...” David.


3

Podczas inicjalizacji dodawałem też zły zestaw. Klasa, którą utrwalam, znajduje się w zestawie nr 1, a mój plik .hbm.xml jest osadzony w zestawie nr 2. Zmieniłem, cfg.AddAssembly(...aby dodać zestaw nr 2 (zamiast zespołu nr 1) i wszystko działało. Dzięki!


3

Aby dodać do odpowiedzi Amola, nie popełnij błędu określając typ klasy interfejsu. Upewnij się, że określisz klasę implementacji . (Tj. Nie używaj IDomainObjectType). Nie to, że popełniłem ten błąd ... :)


2

Powinien być name="Id"? Prawdopodobną przyczyną są literówki.

Następnym krokiem byłoby wypróbowanie tego za pomocą testu nieogólnego, aby upewnić się, że przekazujesz właściwy parametr typu.

Czy możesz opublikować cały komunikat o błędzie?



2

Ten błąd występuje z powodu nieprawidłowej konfiguracji mapowania. Powinieneś sprawdzić, gdzie ustawiłeś .Mappings dla twojej fabryki sesji. Zasadniczo wyszukaj „.Mappings (”) w swoim projekcie i upewnij się, że w poniższym wierszu określono poprawną klasę encji.

.Mappings(m => m.FluentMappings.AddFromAssemblyOf<YourEntityClassName>())

dzięki stary! Zmieniłem projekt, w którym siedziały moje istoty!
viggity

1

Jeśli uruchamiasz testy repozytorium z osobnego zestawu, upewnij się, że plik Hibernate.cfg.xml jest ustawiony na wyjście zawsze w katalogu bin wspomnianego zestawu. To się nie działo w naszym przypadku i otrzymaliśmy powyższy błąd w pewnych okolicznościach.

Zastrzeżenie: może to być nieco ezoteryczna rada, biorąc pod uwagę, że jest to bezpośredni wynik tego, jak budujemy nasze zestawy testów integracji repozytorium (tj. Mamy symboliczne łącze z każdego zestawu testowego do pojedynczego Hibernate.xfg.xml)


1

Nie zapomnij podać informacji o mapowaniu w pliku .config

na przykład

gdzie MyApp.Data jest zestawem zawierającym mapowania


0

Miałem podobny problem, gdy znajdowałem obiekt według identyfikatora ... Wszystko, co zrobiłem, to użycie w pełni kwalifikowanej nazwy w nazwie klasy. To było zanim to było:

find("Class",id)

Obiekt więc wyglądało tak:

find("assemblyName.Class",id)

0

Upewnij się, że wywołałeś CreateCriteria(typeof(DomainObjectType))metodę na Session dla obiektu domeny, który chcesz pobrać z bazy danych.


To jest trwanie, a nie pobieranie.
Joshua Drake

0

Mam podobny problem, ale wszystkie wymienione wymagania są spełnione. W moim przypadku próbuję zapisać jakąś klasę encji (typ OBJEKTE) z powrotem do DB. Inne miejsca działają, ale tylko w tym przypadku zawodzi i podnosi ten wyjątek.

Moim rozwiązaniem (HACK) było ponowne zmapowanie obiektu typu OBJEKTE i ponowne zapisanie go. Nagle to działa. Ale nie pytaj dlaczego.

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

Jeśli inparam przeszedłby bezpośrednio do UpdateAsync (), nie może znaleźć pasującego persystora.

Można to wytłumaczyć sposobem, w jaki NH to robi. Wyprowadza serwer proxy z klasy mapowania i implementuje właściwości z dołączoną brudną obsługą. Zobacz:

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

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

Zabawne jest jednak to, że źródłem inparamjest w rzeczywistości samo repozytorium NH. Tak czy inaczej. Zostanę przy tym hackowaniu ponownego przypisania na następny raz.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.