Relationship 1:N in the Entity Framework

Asked

Viewed 56 times

0

Good afternoon. I am studying the Entityframework and I am not managing to do something that seems to be simple but will not. ( I wanted to make a 1:N relationship between a table for a customer that may have multiple quotes, but quotes can only have one customer.

This is my class Client:

public class Cliente
{
    [Key]
    public int ID { get; set; }
    public double CPF { get; set; }
    public string Nome { get; set; }
    //public Cotacao Cotacao { get; set; }
    public ICollection<Cotacao> Cotacao { get; set; }
    //public virtual IEnumerable<Cotacao> Cotacoes { get; set; }

    public Cliente(double cpf, string nome, ICollection<Cotacao> cotacao)
    {
        CPF = cpf;
        Nome = nome ?? throw new ArgumentNullException(nameof(nome));
        Cotacao = cotacao ?? throw new ArgumentNullException(nameof(cotacao));
    }

    public Cliente(double cpf, string nome)
    {
        CPF = cpf;
        Nome = nome ?? throw new ArgumentNullException(nameof(nome));
    }
}

This is my class Quotation:

public class Cotacao
{   
    [Key]
    public int ID { get; set; }
    public virtual Cliente Cliente { get; set; }
    public string Idade { get; set; }
    public string Genero { get; set; }
    public string Marca { get; set; }
    public string Modelo { get; set; }
    public string AnoFabricacao { get; set; }
    public string AnoModelo { get; set; }


    public Cotacao(Cliente cliente, string idade, string genero, string marca, string modelo, string anoFabricacao, string anoModelo)
    {
        Cliente = cliente;
        Idade = idade;
        Genero = genero;
        Marca = marca;
        Modelo = modelo;
        AnoFabricacao = anoFabricacao;
        AnoModelo = anoModelo;

    }

    public Cotacao(string idade, string genero, string marca, string modelo, string anoFabricacao, string anoModelo)
    {
        Idade = idade;
        Genero = genero;
        Marca = marca;
        Modelo = modelo;
        AnoFabricacao = anoFabricacao;
        AnoModelo = anoModelo;
    }
}

This is my Context:

public partial class ContextDB : DbContext
{
    public DbSet<Cliente> Clientes { get; set; }
    public DbSet<Cotacao> Cotacoes { get; set; }

    public ContextDB() : base("name=ContextDB")
    {

    }
}

And that’s how I’m creating saving the data in the bank:

if (!string.IsNullOrEmpty(cpf))
        {
            using (var ctx = new ContextDB())
            {
                Cliente cliente = new Cliente(double.Parse(cpf), nome);
                Cotacao cotacao = new Cotacao(cliente, idade, genero, marca, modelo, anoFabricacao, anoModelo);


                if (cliente.CPF == cotacao.Cliente.CPF) // Sem esse if, também não vai.
                {
                    ctx.Cotacoes.Add(cotacao);
                    ctx.SaveChanges();
                }
                else
                {
                    ctx.Clientes.Add(cliente);
                    ctx.Cotacoes.Add(cotacao);
                    ctx.SaveChanges();
                }
            }
        }

But every time he creates a new client and does not associate the contract with the client. Os Contratos

Os Clientes

I imagine the problems are in creating two objects, but I don’t know how I would add an existing object in the creation of the other. What I’d be doing wrong?

1 answer

1


Your Quote class has a customer relationship, so you need to specify the foreign key field in it that will be customer related, which usually uses ClienteId, but it is not necessary to be this name.

So in your class leave her like this

public class Cotacao
{   
    [Key]
    public int ID { get; set; }
    public int ClienteId {get; set; }
    [ForeignKey("ClienteId")]
    public virtual Cliente Cliente { get; set; }
    public string Idade { get; set; }
    public string Genero { get; set; }
    public string Marca { get; set; }
    public string Modelo { get; set; }
    public string AnoFabricacao { get; set; }
    public string AnoModelo { get; set; }


    public Cotacao(Cliente cliente, string idade, string genero, string marca, string modelo, string anoFabricacao, string anoModelo)
    {
        Cliente = cliente;
        Idade = idade;
        Genero = genero;
        Marca = marca;
        Modelo = modelo;
        AnoFabricacao = anoFabricacao;
        AnoModelo = anoModelo;

    }

    public Cotacao(string idade, string genero, string marca, string modelo, string anoFabricacao, string anoModelo)
    {
        Idade = idade;
        Genero = genero;
        Marca = marca;
        Modelo = modelo;
        AnoFabricacao = anoFabricacao;
        AnoModelo = anoModelo;
    }
}

So your class will have a 1:N relationship with the customer class.

-> Edition below

I replicated your code on my machine here and did some testing, and it got this way here, and it worked I managed to create customers and quotes for these clietes, and also bringing the quotes in the customer search.

Client class

public class Cliente
     {
        [Key()]
        public int Id { get; set; }
        public string CPF { get; set; }
        public string Nome { get; set; }
        public virtual ICollection<Cotacao> Cotacao { get; set; }

        public Cliente(string cpf, string nome, ICollection<Cotacao> cotacao)
        {
            CPF = cpf;
            Nome = nome ?? throw new ArgumentNullException(nameof(nome));
            Cotacao = cotacao ?? throw new ArgumentNullException(nameof(cotacao));
        }

        public Cliente(string cpf, string nome)
        {
            CPF = cpf;
            Nome = nome ?? throw new ArgumentNullException(nameof(nome));
        }

        public Cliente()
        {
        }
    }
  • First I put the database settings via Fluenteapi in the Contexdb class and also changed the property type CPF for string, is not required but it makes more sense for Cpf to be string.

Class Quotation

public class Cotacao
    {
        [Key()]
        public int Id { get; set; }
        public string Idade { get; set; }
        public string Genero { get; set; }
        public string Marca { get; set; }
        public string Modelo { get; set; }
        public string AnoFabricacao { get; set; }
        public string AnoModelo { get; set; }
        public int ClienteId { get; set; }

        [ForeignKey("ClienteId")]
        public virtual Cliente Cliente { get; set; }

        public Cotacao()
        {

        }

        public Cotacao(Cliente cliente, string idade, string genero, string marca, string modelo, string anoFabricacao, string anoModelo)
        {
            Cliente = cliente;
            Idade = idade;
            Genero = genero;
            Marca = marca;
            Modelo = modelo;
            AnoFabricacao = anoFabricacao;
            AnoModelo = anoModelo;

        }

        public Cotacao(string idade, string genero, string marca, string modelo, string anoFabricacao, string anoModelo)
        {
            Idade = idade;
            Genero = genero;
            Marca = marca;
            Modelo = modelo;
            AnoFabricacao = anoFabricacao;
            AnoModelo = anoModelo;
        }
    }

In the Quotation class I created an empty constructor, because in queries Entity needs an empty constructor.

Contexdb class

public partial class ContextDB : DbContext
    {
        public DbSet<Cliente> Clientes { get; set; }
        public DbSet<Cotacao> Cotacoes { get; set; }

        public ContextDB() : base("name=ContextDB")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Cotacao>().HasRequired(c => c.Cliente).WithMany(c => c.Cotacao);

            base.OnModelCreating(modelBuilder);
        }
    }

I configured the relationships with Fluenteapi, writing the method OnModelCreating.

So I created two client objects and added them to the base, then created the quote objects and added them to the customers via the Clienteid property.

using (var db = new ContextDB())
            {
                //Cria os objetos dos clientes
                var cliente1 = new Cliente("12345678912", "Robson Silva Brito");
                var cliente2 = new Cliente("65415935745", "Eliane Moraes");

                //Adiciona os objetos para inserção
                db.Clientes.Add(cliente1);
                db.Clientes.Add(cliente2);

                //Salva no banco
                db.SaveChanges();

                //Cria os objetos de cotação
                var cotacao1 = new Cotacao("15", "Masculino", "Chevrolet", "Agile", "2011", "2011");
                //Atribuo esse objeto a um cliente com o Id do cliente
                cotacao1.ClienteId = 1;

                var cotacao2 = new Cotacao("25", "Masculino", "Chevrolet", "Corsa", "2011", "2011");
                cotacao2.ClienteId = 2;

                //Adiciona as instancia para inserção
                db.Cotacoes.Add(cotacao1);
                db.Cotacoes.Add(cotacao2);
                //Salva no banco
                db.SaveChanges();

                //Traz todos clientes junto com suas cotações
                var clientes = db.Clientes.ToList();
            }
  • Hey, Robson, thanks for your help, but I still have the same problem. New customer registrations are still generated and quotations continue to be created with these "new" customer Ids, you would have more hints than could be wrong?

  • R.Souza edited the answer there, worked right in the tests I did here. See if it works for you too.

  • If you want to leave the property Clienteid being passed in the constructor also just add it together in any of the constructors, and do not delete the empty constructor option, otherwise at the time of bringing the data you will not be able.

  • Robson, thanks for your help, it really worked out the way you showed it. I added the information you gave me and looked for Fluentapi, it helped me a lot. E I used the information from this link link to search for the first person in the bank with the ID/CPF that enters as information. Thank you very much again, I knew I was missing some things, but I will try to study more to understand all of the Entity, hugs.

  • That’s good that it worked. Entity really is very good and dominalo will give you a good advantage in the constructions of your applications. Flw good study there.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.