Solucionado (ver solução)
Solucionado
(ver solução)
26
respostas

Relacionamento NHIBERNATE

Não estou conseguindo implementar os relacionamentos no banco de dados diretamente da aplicação usando NHibernate, estou com o seguinte erro abaixo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SistemaOCW.Entidade
{
    public class Empresa
    {
        public virtual int Id { get; set; }
        public virtual string Nome { get; set; }
        public virtual string Cnpj { get; set; }
        public virtual string Endereco { get; set; }
        public virtual string Bairro { get; set; }
        public virtual string Cidade { get; set; }
        public virtual string Cep { get; set; }
        public virtual string Telefone { get; set; }
        public virtual string Email { get; set; }
        public virtual string Contato { get; set; }
        public virtual IList<Cliente> Clientes { get; set; }

    }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Empresa">
    <id name ="Id">
      <generator class ="identity"/>
    </id>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/> 
    <bag name="Clientes">
    <key column="EmpresaId"/>
    <one-to-many class="Cliente"/>
  </bag>
  </class>
</hibernate-mapping>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SistemaOCW.Entidade
{
    public class Cliente
    {
        public virtual int Id { get; set; }
        public virtual int Codcliente { get; set; }
        public virtual string Nome { get; set; }
        public virtual string Cnpj { get; set; }
        public virtual string Endereco { get; set; }
        public virtual string Bairro { get; set; }
        public virtual string Cidade { get; set; }
        public virtual string Cep { get; set; }
        public virtual string Telefone { get; set; }
        public virtual string Email { get; set; }
        public virtual string Contato { get; set; }
        public virtual Empresa Empresa { get; set; }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Cliente">
    <id name ="Id">
      <generator class ="identity"/>
    </id>
    <property name="Codcliente"/>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/>
  <many-to-one name="Empresa" column="EmpresaId"/>
     </class>
</hibernate-mapping>
NHibernate.Exceptions.GenericADOException não foi manipulada pelo código do usuário
  HResult=-2146232832
  Message=could not insert: [SistemaOCW.Entidade.Cliente][SQL: INSERT INTO Cliente (Codcliente, Nome, Cnpj, Endereco, Bairro, Cidade, Cep, Telefone, Email, Contato, EmpresaId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
  Source=NHibernate
  SqlString=INSERT INTO Cliente (Codcliente, Nome, Cnpj, Endereco, Bairro, Cidade, Cep, Telefone, Email, Contato, EmpresaId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  StackTrace:
       em NHibernate.Id.Insert.AbstractSelectingDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
       em NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlCommandInfo sql, Object obj, ISessionImplementor session)
       em NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session)
       em NHibernate.Action.EntityIdentityInsertAction.Execute()
       em NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
       em NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       em NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       em NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       em NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
       em NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
       em NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
       em NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
       em NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
       em NHibernate.Impl.SessionImpl.Save(Object obj)
       em SistemaOCW.DAO.ClienteDAO.Adiciona(Cliente cliente) na d:\OCW\SistemaOCW\SistemaOCW\DAO\ClienteDAO.cs:linha 26
       em SistemaOCW.Controllers.ClienteController.Adiciona(Cliente cliente) na d:\OCW\SistemaOCW\SistemaOCW\Controllers\ClienteController.cs:linha 34
       em lambda_method(Closure , ControllerBase , Object[] )
       em System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
       em System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       em System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       em System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
       em System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
  InnerException: MySql.Data.MySqlClient.MySqlException
       HResult=-2147467259
       Message=Cannot add or update a child row: a foreign key constraint fails (`compras`.`cliente`, CONSTRAINT `FKE156C0F996677116` FOREIGN KEY (`Id`) REFERENCES `empresa` (`Id`))
       Source=MySql.Data
       ErrorCode=-2147467259
       Number=1452
       StackTrace:
            em MySql.Data.MySqlClient.MySqlStream.ReadPacket()
            em MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
            em MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId)
            em MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
            em MySql.Data.MySqlClient.MySqlDataReader.NextResult()
            em MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
            em MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
            em MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
            em NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)
            em NHibernate.Id.Insert.AbstractSelectingDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
       InnerException: 
enter code here
26 respostas

Acrescentei na Bag "inverse = true"

Começou a gravar o cliente nao gerou exeption, fui no MySQl e coloquei a selet abaixo:

select empresa.Id, empresa.nome,  cliente.Id, cliente.Nome
from  cliente, empresa
where empresa.Id = cliente.Id

ele me traz uma empresa de Id 1 com um cliente de Id 1 uma empresa de Id2 com cliente de Id 2 uma empresa de Id3 com cliente de Id 3 depois parou de inserir o cliente e voltou o erro acima na session.save() esse relacionamento também esta errado, ele deveria me trazer uma empresa com varios clientes, e varios cliente somente de uma empresa.

Olá Leonardo,

Vamos começar pela query feita por você, vocês está dizendo na query que quer registros da tabela cliente onde o ID da empresa seja igual ao id do cliente. Pelo que entendi pelo seus arquivos hbm, a rotina deveria ser assim:

select empresa.Id, empresa.nome,  cliente.Id, cliente.Nome
from  cliente, empresa
where empresa.Id = cliente.EmpresaId

Pois o que você se confundiu, foi que na tabela empresa o nome do campo do campo é Id e na tabela de clientesó campo com código da empresa é EmpresaID.

Quanto ao erro, me parece ser em outra parte da aplicação, porém relacionado ao mesmo tipo de erro, pois está dizendo o seguinte:

Cannot add or update a child row: a foreign key constraint fails (compras.cliente, CONSTRAINT FKE156C0F996677116 FOREIGN KEY (Id) REFERENCES empresa (Id))

Ao que me parece, está tentando colocar um código de cliente em um campo ID que referencia a tabela empresa. Me corrijam se eu estiver errado.

Só corrigindo o erro de digitação segue a frase que saiu tudo trocado, rs:

Pois o que você se confundiu, foi que na tabela empresa, o nome do campo chave é Id e na tabela cliente, o campo com código da empresa é EmpresaID

.

Rafael; Eu tenho uma empresa cadastrada e quero pegar todos os clientes daquela empresa. Quando faço a consulta no banco de dados (select * from cliente) ele esta me trazendo todos os clientes, só que o campo EmpresaId que deveria guardar a chave da empresa o valor 1 esta null.

realizando a sua consulta que esta certa

select empresa.Id, empresa.nome,  cliente.Id, cliente.Nome
from  cliente, empresa
where empresa.Id = cliente.EmpresaId

ele nao traz nada porque o empresaid nao tabela clienre esta null.

O inverse=true, foi acrescentado após você inserir estes clientes? Pois, talvez você tenha alterado a empresa e aí o merge foi feito e tirado o relacionamento dos clientes com a empresa. Neste caso, eu faria:

update empresa   
set empresaId = 1 
where empresaId is null

E aí observaria a partir disso, incluindo clientes testes e alterando a Empresa. Porque tenho quase certeza que foi o merge que fez isso antes de você colocar "inverse = true".

ops corrigindo.

update Cliente
set empresaId = 1 
where empresaId is null

Realizei esse comando no banco, ele seta os valores nos clientes ja cadastrado, quando cadastro um novo cliente volta a vir valor null. acho que o erro esta vindo da aplicação daquela configuração nas classes de mapeamentos.

Essas modificações nas classes de mapeamento eu fiz depois de ter o banco junto com as tabelas o banco, o relacionamento.

Leonardo, Deixamos passar em branco um detalhe, faltou informar a classe Empresa na tag:

<many-to-one name="Empresa" column="EmpresaId" class="Empresa" />

Agora vai!

Rafael fiz a modificação e nao deu certo, continua vindo o cliente que cadastro com o empresaid null

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Cliente">
    <id name ="Id">
      <generator class ="identity"/>
    </id>
    <property name="Codcliente"/>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/>
    <many-to-one name="Empresa" column="EmpresaId" class = "Empresa"/>
     </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Empresa">
    <id name ="Id">
      <generator class ="identity"/>
    </id>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/> 
    <bag name="Clientes" inverse="true">
    <key column="EmpresaId"/>
    <many-to-one class="Cliente"/>
  </bag>
  </class>
</hibernate-mapping>

Vc pode colocar aqui o método adiciona da cliente dao e a action da controller?

using NHibernate;
using SistemaOCW.DAO;
using SistemaOCW.Entidade;
using SistemaOCW.Infra;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;


namespace SistemaOCW.Controllers
{
    public class ClienteController : Controller
    {  

           public ActionResult Form()
        {
            return View();
        }
        //
        // GET: /Cliente/

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Adiciona(Cliente cliente)
        {

            ISession session = NHibernateHelper.AbreSession();
            ClienteDAO dao = new ClienteDAO(session);       

            dao.Adiciona(cliente);
            session.Close();
            return RedirectToAction("Index");
        }

    }
}
using SistemaOCW.Entidade;
using System;
using System.Collections.Generic;
using System.EnterpriseServices;
using System.Linq;
using System.Web;
using SistemaOCW.Infra;
using NHibernate;

namespace SistemaOCW.DAO
{
    public class ClienteDAO
    {
        private ISession session;


        public ClienteDAO(ISession session)
        {
            this.session = session;
        }


        public void Adiciona(Cliente cliente)
        {
            NHibernate.ITransaction transacao = session.BeginTransaction();
            session.Save(cliente);
            transacao.Commit();
        }


        // public Cliente BuscaPorId(int id)
        //  {
        //  return session.Get<Cliente>(id);
        //  }
    }
}

Blz. Você pode colocar aqui a view do form que cadastra o cliente, esqueci pedir.

@{
    ViewBag.Title = "Form";
}

<h2>Cadastro Cliente</h2>

<form action="@Url.Action("Adiciona", "Cliente")" method="post">
    <label>
        Codigo:
        <input type="text" name="cliente.Codcliente" />
        Nome:
        <input type="text" name="cliente.Nome" />
         CNPJ:
        <input type="text" name="cliente.Cnpj" />
         Endereco:
        <input type="text" name="cliente.Endereco" />
         Bairro:
        <input type="text" name="cliente.Bairro" />
         Cidade:
        <input type="text" name="cliente.Cidade" />
         CEP:
        <input type="text" name="cliente.Cep" />
         Telefone:
        <input type="text" name="cliente.Telefone" />
         Email:
        <input type="text" name="cliente.Email" />
         Contato:
        <input type="text" name="cliente.Contato" />

    </label>
    <input type="submit" value="Adicionar"/>
</form>

Oi Leonardo

Parece que a tabela de clientes do seu banco de dados foi criada incorretamente.

Você poderia executar os comandos abaixo no mysql e depois postar o resultado?

Primeiro comando:

show create table Empresa;

e o segundo comando:

show create table Cliente;
CREATE TABLE `empresa` (
   `Id` int(11) NOT NULL AUTO_INCREMENT,
   `Nome` varchar(255) DEFAULT NULL,
   `Cnpj` varchar(255) DEFAULT NULL,
   `Endereco` varchar(255) DEFAULT NULL,
   `Bairro` varchar(255) DEFAULT NULL,
   `Cidade` varchar(255) DEFAULT NULL,
   `Cep` varchar(255) DEFAULT NULL,
   `Telefone` varchar(255) DEFAULT NULL,
   `Email` varchar(255) DEFAULT NULL,
   `Contato` varchar(255) DEFAULT NULL,
   PRIMARY KEY (`Id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
CREATE TABLE `cliente` (
   `Id` int(11) NOT NULL AUTO_INCREMENT,
   `Codcliente` int(11) DEFAULT NULL,
   `Nome` varchar(255) DEFAULT NULL,
   `Cnpj` varchar(255) DEFAULT NULL,
   `Endereco` varchar(255) DEFAULT NULL,
   `Bairro` varchar(255) DEFAULT NULL,
   `Cidade` varchar(255) DEFAULT NULL,
   `Cep` varchar(255) DEFAULT NULL,
   `Telefone` varchar(255) DEFAULT NULL,
   `Email` varchar(255) DEFAULT NULL,
   `Contato` varchar(255) DEFAULT NULL,
   `EmpresaId` int(11) DEFAULT NULL,
   PRIMARY KEY (`Id`),
   KEY `EmpresaId` (`EmpresaId`),
   CONSTRAINT `FKE156C0F9105A37B` FOREIGN KEY (`EmpresaId`) REFERENCES `empresa` (`Id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

Leonardo, onde você informa o ID da empresa no formulário de cadastro de clientes? Pelo que entendi o problema seria que todo cliente está com IdEmpresa nulo, mas no form não existe esta informação?

Rafael; Eu nao tenho um campo texto para preencher manual, no meu entendimento como vou ter so uma empresa cadastrada penso que o id da empresa iria ser automático para o cliente, nao sei se isso é possível, estou pesquisando na internet varia formas de fazer isso mas ainda nao achei a solução.

Rafael; Se acho que se fosse assim na linha do seu raciocinio eu poderia simplesmente comparar cod cliente com id da empresa, iria preencher todos os codcliente com id 1 e a empresa ja estaria com id 1. ai nao precisaria nem de chave estrangeira.

CONSTRAINT FKE156C0F9105A37B FOREIGN KEY (EmpresaId) REFERENCES empresa (Id) ou seja o Forg Key chama EMpresaID e não ID como ta no código do erro do Nhibernate

Paulo; Voce esta me dizendo que meu codgo tem que ficar assim:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Empresa">
    <id name ="EmpresaId">
      <generator class ="identity"/>
    </id>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/>
    <bag name="Clientes">
      <key column="EmpresaId"/>
      <one-to-many class="Cliente"/>
    </bag>
  </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Cliente">
    <id name ="Id">
      <generator class ="identity"/>
    </id>
    <property name="Codcliente"/>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/>
    <many-to-one name="Empresa" column="EmpresaId" class = "Empresa"/>
  </class>
</hibernate-mapping>

Mudei todo o codigo para ver se dava certo, e deu outro erro.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Empresa">
    <id name ="Id">
    <generator class ="identity"/>
    </id>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/> 
    <bag name="Clientes">
    <key column= "Id"/>
    <one-to-many class="Cliente"/>  
      </bag>
  </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Cliente">
    <id name ="Id">
      <generator class ="identity"/>
    </id>
    <property name="Codcliente"/>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/>
    <many-to-one name="empresa" column="Id" class = "Empresa"/>
  </class>
</hibernate-mapping>

Inseri uma empresa, depois inseri um cliente, olhei no banco nao deu certo, fui inserir um segundo cliente deu esse erro:

NHibernate.Exceptions.GenericADOException não foi manipulada pelo código do usuário
  HResult=-2146232832
  Message=could not insert: [SistemaOCW.Entidade.Cliente][SQL: INSERT INTO Cliente (Codcliente, Nome, Cnpj, Endereco, Bairro, Cidade, Cep, Telefone, Email, Contato, Id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
  Source=NHibernate
  SqlString=INSERT INTO Cliente (Codcliente, Nome, Cnpj, Endereco, Bairro, Cidade, Cep, Telefone, Email, Contato, Id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  StackTrace:
       em NHibernate.Id.Insert.AbstractSelectingDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
       em NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlCommandInfo sql, Object obj, ISessionImplementor session)
       em NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session)
       em NHibernate.Action.EntityIdentityInsertAction.Execute()
       em NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
       em NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       em NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       em NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       em NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
       em NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
       em NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
       em NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
       em NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
       em NHibernate.Impl.SessionImpl.Save(Object obj)
       em SistemaOCW.DAO.ClienteDAO.Adiciona(Cliente cliente) na d:\OCW\SistemaOCW\SistemaOCW\DAO\ClienteDAO.cs:linha 26
       em SistemaOCW.Controllers.ClienteController.Adiciona(Cliente cliente) na d:\OCW\SistemaOCW\SistemaOCW\Controllers\ClienteController.cs:linha 35
       em lambda_method(Closure , ControllerBase , Object[] )
       em System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
       em System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       em System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       em System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
       em System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
  InnerException: MySql.Data.MySqlClient.MySqlException
       HResult=-2147467259
       Message=Cannot add or update a child row: a foreign key constraint fails (`compras`.`cliente`, CONSTRAINT `FKE156C0F996677116` FOREIGN KEY (`Id`) REFERENCES `empresa` (`Id`))
       Source=MySql.Data
       ErrorCode=-2147467259
       Number=1452
       StackTrace:
            em MySql.Data.MySqlClient.MySqlStream.ReadPacket()
            em MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
            em MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId)
            em MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
            em MySql.Data.MySqlClient.MySqlDataReader.NextResult()
            em MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
            em MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
            em MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
            em NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)
            em NHibernate.Id.Insert.AbstractSelectingDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
       InnerException:

Voltei olhei no banco, ele cria duas fk

Cliente    CREATE TABLE `cliente` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Codcliente` int(11) DEFAULT NULL,
  `Nome` varchar(255) DEFAULT NULL,
  `Cnpj` varchar(255) DEFAULT NULL,
  `Endereco` varchar(255) DEFAULT NULL,
  `Bairro` varchar(255) DEFAULT NULL,
  `Cidade` varchar(255) DEFAULT NULL,
  `Cep` varchar(255) DEFAULT NULL,
  `Telefone` varchar(255) DEFAULT NULL,
  `Email` varchar(255) DEFAULT NULL,
  `Contato` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  KEY `Id` (`Id`),
  KEY `Id_2` (`Id`),
  CONSTRAINT `FKE156C0F996677116` FOREIGN KEY (`Id`) REFERENCES `empresa` (`Id`),
  CONSTRAINT `FKE156C0F9CEE14BB0` FOREIGN KEY (`Id`) REFERENCES `empresa` (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
Empresa    CREATE TABLE `empresa` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Nome` varchar(255) DEFAULT NULL,
  `Cnpj` varchar(255) DEFAULT NULL,
  `Endereco` varchar(255) DEFAULT NULL,
  `Bairro` varchar(255) DEFAULT NULL,
  `Cidade` varchar(255) DEFAULT NULL,
  `Cep` varchar(255) DEFAULT NULL,
  `Telefone` varchar(255) DEFAULT NULL,
  `Email` varchar(255) DEFAULT NULL,
  `Contato` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

Oi Leonardo

O problema desse novo mapeamento é que agora você está falando para o NHibernate utilizar a coluna Id da tabela de clientes tanto como chave primária quanto chave estrangeira para a Empresa, dessa forma, só é possível inserir um Cliente se já existir uma empresa com o mesmo Id desse novo cliente. Esse tipo de mapeamento só é utilizado em situações muito específicas (em caso de herança, por exemplo).

O correto seria:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Empresa">
    <id name ="Id">
    <generator class ="identity"/>
    </id>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/> 
    <bag name="Clientes">
      <key column= "EmpresaId"/>
      <one-to-many class="Cliente"/>  
    </bag>
  </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SistemaOCW"
                   namespace="SistemaOCW.Entidade">
  <class name ="Cliente">
    <id name ="Id">
      <generator class ="identity"/>
    </id>
    <property name="Codcliente"/>
    <property name="Nome"/>
    <property name="Cnpj"/>
    <property name="Endereco"/>
    <property name="Bairro"/>
    <property name="Cidade"/>
    <property name="Cep"/>
    <property name="Telefone"/>
    <property name="Email"/>
    <property name="Contato"/>
    <many-to-one name="empresa" column="EmpresaId" class = "Empresa"/>
  </class>
</hibernate-mapping>

Antes de testar esse mapeamento, execute um drop table para remover as tabelas Cliente e Empresa do seu banco de dados para que as foreign keys que foram criadas sejam descartadas.

Sim Victor refiz os passos que você pediu, esta gravando a empresa, esta gravando o cliente, quero saber se com isso ele teria qu preencher automaticamente o empresaid no cliente, para quando eu executar essa consulta abaixo já trazer todos os clientes daquela empresa.

select empresa.Id, empresa.nome,  cliente.Id, cliente.Nome
from  cliente, empresa
where empresa.Id = cliente.EmpresaId

ou eu vou ter que criar um mais um campo e preencher ele manualmente com o id da empresa que quero que o cliente faça parte.

solução!

Você tem duas opções:

colocar um novo campo no seu formulário, mesmo que seja um campo hidden que já vem preenchido com o id correto da empresa

ou você poderia modificar o código da sua lógica que grava o cliente com o NHibernate para fazer com que ela preencha o id da empresa.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software