Array
(
)

Associação vários para 1 ( Csharp +(razor + asp.net mvc 3)

Hugo
|
MVP
    06 nov 2012

Olá Pessoal
Tenho uma classe denominada de DadosPessoaJuridica, que tem uma associação de vários(*) para um(1) com a classe de Pessoa, veja:
#Código

    public class DadosPessoaJuridica
    {

        [Key]
        public int Id { get; set; }

        public string CNPJ { get; set; }

        public int? PessoaId { get; set; }
        public virtual Pessoa Pessoa { get; set; }
    }


    public class Pessoa
    {
        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "(Requerido)")]
        [DisplayName("Nome")]
        public string Nome { get; set; }

        public virtual DadosPessoaJuridica DadosPessoaJuridica { get; set; }
    }

O problema é que o .NET não está aceitando essa associação. O seguinte erro é emitido:

Citação:

Unable to determine the principal end of an association between the types 'Sys.Models.PessoaJuridica' and 'Sys.Models.Pessoa'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

Se algum colega puder me ajudar, ficarei muito grato.
Abraços

Robson Robsonalves.net
   - 07 nov 2012


Quando preciso realizar este tipo de associação eu prefiro criar uma lista de objetos para gerar o relacionamento.

No caso:

#Código

    public class DadosPessoaJuridica
    {

        [Key]
        public int Id { get; set; }
        public string CNPJ { get; set; }
        public int? PessoaId { get; set; }
    }


    public class Pessoa
    {
        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "(Requerido)")]
        [DisplayName("Nome")]
        public string Nome { get; set; }

        public virtual IList<DadosPessoaJuridica> DadosPessoaJuridica { get; set; }
    }


Sendo sincero deve existir patterns ou melhores práticas para realizar este processo.

Eu também removeria o #Código
public virtual Pessoa Pessoa { get; set; }


da classe DadosPessoaJuridica, assim ao acessar o objeto Pessoa, eu tenho a lista (*) dos dados jurídico dela;

Hugo
|
MVP
    07 nov 2012


Citação:

Quando preciso realizar este tipo de associação eu prefiro criar uma lista de objetos para gerar o relacionamento.

No caso:

#Código

    public class DadosPessoaJuridica
    {

        [Key]
        public int Id { get; set; }
        public string CNPJ { get; set; }
        public int? PessoaId { get; set; }
    }


    public class Pessoa
    {
        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "(Requerido)")]
        [DisplayName("Nome")]
        public string Nome { get; set; }

        public virtual IList<DadosPessoaJuridica> DadosPessoaJuridica { get; set; }
    }


Sendo sincero deve existir patterns ou melhores práticas para realizar este processo.

Eu também removeria o #Código
public virtual Pessoa Pessoa { get; set; }


da classe DadosPessoaJuridica, assim ao acessar o objeto Pessoa, eu tenho a lista (*) dos dados jurídico dela;


Bom dia Robson, obrigado pela resposta.

Eu tenho alguns questionamentos, são eles:

1º) No seu exemplo, você está sugerindo o uso de uma lista, então como ficaria o código abaixo no meu CONTROLLER de Pessoa para ler essa lista?

#Código
   var totalReg = _db.Pessoas.Where(filtro).Count();
   var data = _db.Pessoas.OrderBy(a => a.Nome).ToList();
   var registros = data.Select(x => new
            {
                x.Id,
                x.Nome,
                x.DadosPessoaJuridica.CNPJ
            });
            
   return Json(new
            {
                rows = registros,
                total = totalReg,
                success = true
            }, JsonRequestBehavior.AllowGet);


Te pergunto isso, porque na leitura acima, o .NET emitiu um erro:
Citação:
System.NullRefenceException: Referência de objeto não definida para uma instância de um objeto.
. Acredito que isso ocorreu porque, por enquanto, o campo CNPJ
está nulo ou não existem dados na tabela. Então, como eu faço nessa situação?

2º) Procurando mais informações na documentação do .NET, a microsoft sugere que nestes casos deveríamos usar uma tal FLUENT API. Eu fiz assim e deu certo, mas gostaria de sua opinião Robson, até porque sou iniciante em .NET, veja:
#Código
            modelBuilder.Entity<Pessoa>()
            .HasOptional(b => b.DadosPessoaJuridica)
            .WithMany(a => a.PessoaId);

Robson Robsonalves.net
   - 07 nov 2012


Citação:

1) Te pergunto isso, porque na leitura acima, o .NET emitiu um erro:
Citação:
System.NullRefenceException: Referência de objeto não definida para uma instância de um objeto.
. Acredito que isso ocorreu porque, por enquanto, o campo CNPJ
está nulo ou não existem dados na tabela. Então, como eu faço nessa situação?

2º) Procurando mais informações na documentação do .NET, a microsoft sugere que nestes casos deveríamos usar uma tal FLUENT API. Eu fiz assim e deu certo, mas gostaria de sua opinião Robson, até porque sou iniciante em .NET, veja:


Bem o primeiro erro aconteceu pq é necessário criar uma instância da lista. então:

#Código

    public class DadosPessoaJuridica
    {

        [Key]
        public int Id { get; set; }
        public string CNPJ { get; set; }
        public int? PessoaId { get; set; }
    }


    public class Pessoa
    {
        public Pessoa()
       {
        DadosPessoaJuridica = new IList<DadosPessoaJuridica>();
       }


        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "(Requerido)")]
        [DisplayName("Nome")]
        public string Nome { get; set; }

        public virtual IList<DadosPessoaJuridica> DadosPessoaJuridica { get; set; }
    }


O Fluent API eu não conheço, mas fiz umas pesquisas e entendi que é uma API (como o próprio nome traz) que utiliza as classes POCO (seu Model) de forma fácil utilizando métodos indicando o que você quer, ele é mais intuitivo para trabalhar. Tornando o código legível quanto as intenções.

É legal utilizar o fluentAPI, você vai ter uma curva de aprendizagem, entretanto estará utilizando uma estrutura que foi concebida por dois Ases do desenvolvimento: Eric Evans e Martin Fowler.

Hugo
|
MVP
    07 nov 2012

Muito obrigado pelas explicações Robson.

Forte abraço e Deus abencoe.