Save Register in Bank with Entity

Asked

Viewed 385 times

1

Dear colleagues.

I’m developing an application C# Winform with database SqlServer and Entity framework. As I am inexperienced, I have been learning through the Internet. I’m having a hard time understanding and implementing some concepts regarding object orientation regarding database manipulation.

I’ll put down the parts of my system to see if they can help me make this code work. To be more objective, my code until it was working but without the proper relationships between the tables. When I modified it so that the tables had relationships began to give errors, as this following.

I appreciate the help.

System.Data.Entity.Infrastructure.Dbupdateexception Hresult=0x80131501 Message=Entities in 'Bancocontexto.Pedidoctx' participate in the 'Cliente_pedidoprincipalx' Relationship. 0 Related 'Cliente_pedidoprincipalx_source' Were found. 1 'Cliente_pedidoprincipalx_source' is expected.

namespace DAL.MODEL
{
    public class Cliente
    {
        public Cliente()
        {
            this.PedidoPrincipalX = new List<PedidoPrincipal>();
        }

        public int ClienteId { get; set; }
        public string Nome { get; set; }

        public virtual ICollection<PedidoPrincipal> PedidoPrincipalX { get; set; }
    }
}

namespace DAL.MODEL
{
    public class PedidoPrincipal
    {
        public int PedidoId { get; set; }
        public DateTime DataEmissao { get; set; }
        public Decimal Total { get; set; }

        public int FK_ClienteId { get; set; }
        public virtual Cliente ClienteX { get; set; }
    }
}

namespace DAL.MAPPING
{
    public class ClienteMap : EntityTypeConfiguration<Cliente>
    {
        public ClienteMap()
        {
            ToTable("Cliente");
            HasKey(c => c.ClienteId);
            Property(c => c.ClienteId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            HasMany(X => X.PedidoPrincipalX);
        }
    }
}


namespace DAL.MAPPING
{
    public class PedidoPrincipalMap : EntityTypeConfiguration<PedidoPrincipal>
    {
        public PedidoPrincipalMap()
        {
            ToTable("PedidoPrincipal");
            HasKey(p => p.PedidoId);
            Property(p => p.PedidoId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            HasRequired(X => X.ClienteX);
        }
    }
}

Code snippet to save to bank:

private void btnSalvar_Click(object sender, EventArgs e)
{
    PedidoPrincipalRepositorio app = new PedidoPrincipalRepositorio();

    PedidoPrincipal pedido = new PedidoPrincipal();

    pedido.FK_ClienteId = Int32.Parse(txtCodigoCli.Text);

    pedido.DataEmissao = DateTime.Now;
    pedido.Total = decimal.Parse(txtValorTotal.Text);

    app.Adicionar(pedido);
    app.SalvarTodos();
}
  • Are you using Codefirst? If so, are you free to define field names and relationships? I say this because Codefirst has a very simple way of doing the relationship, which will help you even with CRUD

  • Yes Rodrigo. I’m using Codefirst.

1 answer

1


First we will make some changes to your Model, to make your life easier, we will use the conventions of Code First.

namespace DAL.MODEL{

    public class Cliente
    {
        public Cliente()
        {
            this.PedidoPrincipalX = new List<PedidoPrincipal>();
        }

        public int Id { get; set; }
        public string Nome { get; set; }

        public virtual ICollection<PedidoPrincipal> PedidoPrincipalX { get; set;} 
    }
}

Modifications

  • Replaces public int ClienteId { get; set; }for public int Id { get; set; }, in this way we use the conversion of EPH, thus he comes to understand that ID is the primary key of the entity Client, and will use that same key as FK, in their relationships

namespace DAL.MODEL
{
    public class PedidoPrincipal
    {
        public int Id { get; set; }
        public DateTime DataEmissao { get; set; }
        public Decimal Total { get; set; }
        public int ClienteId {get;set;}

        public virtual Cliente ClienteX { get; set; }
    }
}

Modifications:

  • Replaces public int PedidoId { get; set; } by public int Id { get; set; }`, at least from above, to maintain the convention, thus the simple fact of using the virtual properties, will cause the EPH understand the relationship automatically

  • I removed public int FK_ClienteId { get; set; }, because we adopt the conventions of EPH, this property becomes unnecessary, and may even hinder the EPH.

  • Includes public int ClienteId {get;set;}, replacing the removed property, so you can use it to connect the customer to the order. Note: You must follow the writing pattern, {class name+Id}, so the EF will identify this properties as FK.


Well, now that we’ve solved the model, let’s go to Mappings:

namespace DAL.MAPPING{

    public class ClienteMap : EntityTypeConfiguration<Cliente>
    {
        public ClienteMap(){
            Property(c => c.ClienteId)
              .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        }
    }
}


namespace DAL.MAPPING
{
    public class PedidoPrincipalMap : EntityTypeConfiguration<PedidoPrincipal>{
        public PedidoPrincipalMap()
        {
            Property(p => p.PedidoId)                   
               .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        }
    }
 }

Modifications:

  • We leave only the configuration of HasDatabaseGeneratedOption, as I said above, using the conventions of EPH, all the relationship part is already created automatically, so it becomes unnecessary this setting by Fluent Api.

This way your code gets clean, easy to understand, and decrease those chances of relationship mistakes. The link I passed on the conventions also has several tutorials on things you will need, I think a good, will help you a lot in this beginning, was what I used as a source of study to learn.

  • Thank you Rodrigo. I will implement.

  • Hello Rodrigo. Now you are recording in the bank, but another problem has arisen. In this part of the application, is an order screen, I need to inform a customer is already registered, this is OK, and register an order for the customer. The problem is, p/ locate the customer in the bank, created a client instance, and did the search in the bank. Now fill in the order data on screen p/ write to the database. You have a relationship with the customer chart, but you’re not saving the customer in the order table. After saving the order, in the table the column where the client code should appear is NULL.

  • Sorry, it was my fault to include in the class PedidoPrincipal the property public int ClienteId {get;set;}, now just fill in the customer id. Note: It has to be exactly in this pattern {Class name+Id}, to follow the conventions, in this way the EF understands this properties as the foreign key to Cliente.

Browser other questions tagged

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