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.

Sara Chipps
źródło
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>
.
.
Andy S.
źródło
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.

Chris Vosnidis
źródło
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!

nHibernate User
źródło
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>
basarat
źródło
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.

Nickmaovich
źródło
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.

David
źródło
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!

Seth
źródło
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 ... :)

goku_da_master
źródło
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?

Matt Hinze
źródło
2

Miałem ten sam problem, ponieważ w metodzie Configuration.AddAssembly () dodawałem zły zespół.

IdontCareAboutReputationPoints
źródło
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>())
Arkadas Kilic
źródło
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)


źródło
1

Nie zapomnij podać informacji o mapowaniu w pliku .config

na przykład

gdzie MyApp.Data jest zestawem zawierającym mapowania


źródło
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)
Jeff Atwood
źródło
0

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

Amol
źródło
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.

Robetto
źródło