NHibernate.MappingException: sem persistência para: XYZ

134

Agora, antes que você diga: eu fiz o Google e meu hbm.xmlarquivo é um recurso incorporado.

Aqui está o código que estou chamando:

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

Aqui está o meu arquivo de mapeamento para a classe:

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

Alguém já correu para esse problema antes?

Aqui está a mensagem de erro completa:

MappingException: sem persister para: HQData.Objects.SubCategory] NHibernate.Impl.SessionFactoryImpl.GetEntityPersister (String entityName, Boolean throwIfNotFound)
 em c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionFactoryImpl.cs: 766 NHibernate.Impl.SessionFactoryImpl.GetEntityPersister (String entityName)
 em c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionFactoryImpl.cs: 752 NHibernate.Event.Default.DefaultLoadEventListener.OnLoad (evento LoadEvent, LoadType loadType)
 em c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Evento \ Padrão \ DefaultLoadEventListener.cs: 37 NHibernate.Impl.SessionImpl.FireLoad (evento LoadEvent, LoadType loadType)
 em c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 2054 NHibernate.Impl.SessionImpl.Get (String entityName, ID do objeto)
 em c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 1029 NHibernate.Impl.SessionImpl.Get (Tipo entityClass, ID do objeto)
 em c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 1020 NHibernate.Impl.SessionImpl.Get (ID do objeto)
 Em c: \ CSharp \ NH2.0.0 \ nhibernate \ src \ NHibernate \ Impl \ SessionImpl.cs: 985 HQData.DataAccessUtils.NHibernateObjectHelper.LoadDataObject (ID de Int32)
 em C: \ Desenvolvimento \ HQChannelRepo \ Aplicativo de canal HQ \ HQChannel \ HQData \ DataAccessUtils \ NHibernateObjectHelper.cs: 42 HQWebsite.LocalSearch.get_subCategory ()
 em C: \ Development \ HQChannelRepo \ Aplicativo de canal HQ \ HQChannel \ HQWebsite \ LocalSearch.aspx.cs: 17 HQWebsite.LocalSearch.Page_Load (remetente do objeto, EventArgs e)
 em C: \ Development \ HQChannelRepo \ Aplicativo de canal HQ \ HQChannel \ HQWebsite \ LocalSearch.aspx.cs: 27 System.Web.Util.CalliHelper.EventArgFunctionCaller (IntPtr fp, Objeto o, Objeto t, EventArgs e) +15 System.Web .Util.CalliEventHandlerDelegateProxy.Callback (Remetente do objeto, 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

Atualização , eis a solução para o meu cenário: eu havia alterado algum código e não estava adicionando o Assembly ao arquivo de configuração durante o tempo de execução.

Sara Chipps
fonte
Eu tive o mesmo erro, mas um problema diferente. Session.Load ("SearchItem", searchItemID) como SearchItem retorna um erro de mapeamento, Session.Load <SearchItem> (searchItemID) não (e é uma maneira menos propensa a erros de fazê-lo de qualquer maneira.
Kendrick

Respostas:

101

Parece que você esqueceu de adicionar um conjunto de mapeamento à configuração de fábrica da sessão.

Se você estiver usando o 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
fonte
7
Como fazer isso no Fluent NHibernate, estou desenvolvendo um padrão em um projeto separado, para não ter acesso ao assembly do usuário?
Mustafa Magdy
Se você não conseguir fazer referência ao assembly do usuário, acho que não poderá usar o Fluent NHibernate.
Andy S
91

Algo óbvio, mas bastante útil para alguém novo no NHibernate.

Todos os arquivos de mapeamento XML devem ser tratados como recursos incorporados, e não como o conteúdo padrão . Esta opção é configurada editando o atributo Build Action nas propriedades do arquivo.

Os arquivos XML são incorporados ao assembly e analisados ​​na inicialização do projeto durante a fase de configuração do NHibernate.

Chris Vosnidis
fonte
1
Haleluia, eu tenho isso como um Embedded resource, mas quando o copiei de um computador para outro, o arquivo perdeu essa propriedade. Cocei minha cabeça por alguns bons minutos.
Dragos Durlut
1
@DragosDurlut o arquivo do projeto (.csproj) que salva as informações dos arquivos do projeto, não o arquivo em si.
Wagner Leonardi
50

Meu problema foi que esqueci de colocar o .hbm no nome do xml de mapeamento. Também certifique-se de torná-lo um recurso incorporado!

Usuário nHibernate
fonte
1
Esse também foi meu erro!
Gringo
Este também foi o meu problema, receba o mesmo erro do Q ao obter. Ao tentar consultar todos os objetos desse tipo, nenhum erro, apenas um conjunto de resultados vazio!
Christoph
Arg - esqueceu o .hbm também. Obrigado!
Dr. C. Hilarius
42

Eu tirei isso daqui :

No meu caso, a classe de mapeamento não era pública. Em outras palavras, em vez de:

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

Eu só tinha:

class UserMap : ClassMap<user>
basarat
fonte
Obrigado, você acabou de me salvar de um pouco de dor de cabeça. :)
Rytmis
2
Se você estiver usando o Fluent, eu diria que essa seria a causa mais comum. Obrigado, foi muito fácil perder.
Richard Neil Ilagan 08/03/11
1
Obrigado! Ao verificar se eu tornei minhas aulas de mapeamento públicas ou não, descobri que não havia escrito uma classe de mapeamento para essa entidade - oops! :) me salvou muito tempo !!
Jen
28

Gastando cerca de 4 horas de googling e stackoverflowing , tentando tudo de coisas por lá, eu encontrei o meu erro:

Meu arquivo de mapeamento foi chamado .nbm.xml em vez de .hbm.xml . Isso foi insano.

Nickmaovich
fonte
9
Argh, apenas fiz o mesmo, exceto que eu o tinha apenas como .xml em vez de .hbm.xml. Talvez deve haver algumas dicas nos erros :)
Rezler
2
AMD. Não acredito que fiz isso. Eu estava procurando horas no mapeamento de arquivos por erros e, ao que parece, eu havia cometido um erro de digitação no nome do arquivo ... doh. Obrigado! Estremeço ao pensar por quanto tempo eu estaria arrancando meu cabelo se não tivesse tropeçado nisso.
kamui
1
Uau, boa captura - eu estava puxando meu cabelo para esse problema. Olhei meu arquivo xml centenas de vezes e não conseguia descobrir por que não estava funcionando como os outros. Na verdade, estava faltando a parte ".hbm" do nome do arquivo. Obrigado!
Winger
Você salvou minhas horas. Obrigado
Manjay_TBAG
4

Eu tive um problema semelhante e resolvi como a seguir:

Eu estou trabalhando no MS SQL 2008, mas na configuração do NH eu tinha um dialeto ruim: NHibernate.Dialect. MsSql2005Dialect se eu corrigi-lo para: NHibernate.Dialect. MsSql2008Dialect , tudo está funcionando bem, sem uma exceção "Não persiste para: ..." David.

David
fonte
3

Eu também estava adicionando o assembly errado durante a inicialização. A classe que estou persistindo está no assembly nº 1 e meu arquivo .hbm.xml está incorporado no assembly nº 2. Mudei cfg.AddAssembly(...para adicionar a montagem nº 2 (em vez da montagem nº 1) e tudo funcionou. Obrigado!

Seth
fonte
3

Para adicionar à resposta da Amol, não cometa o erro de especificar o tipo de classe Interface. Certifique-se de especificar a classe de implementação . (Ou seja, não use IDomainObjectType). Não que eu cometi esse erro ... :)

goku_da_master
fonte
2

Deveria ser name="Id" ? Erros de digitação são uma causa provável.

O próximo passo seria testá-lo com um teste não genérico para garantir que você está passando no parâmetro de tipo apropriado.

Você pode postar a mensagem de erro inteira?

Matt Hinze
fonte
2

Eu tive o mesmo problema porque estava adicionando o assembly errado no método Configuration.AddAssembly ().

IdontCareAboutReputationPoints
fonte
2

Este erro ocorre devido à configuração de mapeamento inválida. Você deve verificar onde definiu .Mappings para sua fábrica de sessões. Pesquise basicamente ".Mappings (") no seu projeto e verifique se especificou a classe de entidade correta na linha abaixo.

.Mappings(m => m.FluentMappings.AddFromAssemblyOf<YourEntityClassName>())
Arkadas Kilic
fonte
valeu cara! Eu mudei o projeto em que minhas entidades estavam sentadas!
Viggity
1

Se estiver executando testes no repositório a partir de um assembly separado, verifique se o Hibernate.cfg.xml está definido para saída sempre no diretório bin do referido assembly. Isso não estava acontecendo para nós e recebemos o erro acima em determinadas circunstâncias.

Isenção de responsabilidade: este pode ser um conselho um pouco esotérico, já que é um resultado direto de como estruturamos nossos conjuntos de teste de integração de repositório (ou seja, temos um link simbólico de cada conjunto de teste para um único Hibernate.xfg.xml)


fonte
1

Não se esqueça de especificar informações de mapeamento no arquivo .config

por exemplo

onde MyApp.Data é um assembly que contém seus mapeamentos


fonte
0

Teve um problema semelhante ao encontrar um objeto por id ... Tudo o que fiz foi usar o nome completo no nome da classe. Isso é Antes de ser:

find("Class",id)

Objeto, tornando-se assim:

find("assemblyName.Class",id)
Jeff Atwood
fonte
0

Certifique-se de ter chamado o CreateCriteria(typeof(DomainObjectType))método na sessão para o objeto de domínio que você deseja buscar no banco de dados.

Amol
fonte
Esta é uma persistência, não uma busca.
Joshua Drake
0

Eu tenho um problema semelhante, mas todos os requisitos mencionados são atendidos. No meu caso, tento salvar alguma classe de entidade (Type of OBJEKTE) de volta no banco de dados. Outros locais funcionam, mas somente nesse caso ele falha e gera essa exceção.

Minha solução (HACK) foi mapear novamente o objeto do tipo OBJEKTE novamente e armazená-lo. De repente, funciona. Mas não pergunte o porquê.

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

Se o inparam for direto para UpdateAsync (), ele não poderá encontrar um persistente correspondente.

Isso poderia ser explicado pela maneira como a NH faz isso. Deriva um proxy da sua classe de mapeamento e implementa as propriedades com manipulação suja incluída. Veja isso:

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

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

O mais engraçado é que a fonte de inparamfato é o próprio repositório NH. Enfim. Eu fico com esse hack de redesignação pela próxima vez.

Robetto
fonte