Entity Framework Navigation Property

Asked

Viewed 67 times

1

I am trying to execute the following code, but it is giving error where it is trying to re-enter the state in my bank, however it was searched through another connection

I know that a solution would be to direct the Estadoid, but I would like to use Navigation only to relate the records, I mean, I do not want the state to be saved along with the city. What could you do to resolve this issue?

static void Main(string[] args)
    {
        Estado estado = GetEstado();

        using(TesteContext context = new TesteContext())
        {
            Cidade cidade = new Cidade();                
            cidade.Estado = estado;
            cidade.Descricao = "SM";
            context.Cidade.Add(cidade);
            context.SaveChanges();
        }
    }

    static Estado GetEstado()
    {
        using (TesteContext context = new TesteContext())
        {
            var estado = context.Estado.FirstOrDefault(a => a.EstadoId == 43);

            if (estado == null)
            {
                estado = new Estado();
                estado.EstadoId = 43;
                estado.Descricao = "RS";
                context.Estado.Add(estado);
                context.SaveChanges();
            }

            return estado;
        }
    }

    public class TesteContext: DbContext
    {
        public DbSet<Estado> Estado { get; set; }

        public DbSet<Cidade> Cidade { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            Database.SetInitializer<TesteContext>(new CreateDatabaseIfNotExists<TesteContext>());
            base.OnModelCreating(modelBuilder);
        }
    }

    public class Estado
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
        [Key]
        public int EstadoId { get; set; }

        [MaxLength(100)]
        [Required]
        public string Descricao { get; set; }
    }

    public class Cidade
    {
        [Key]            
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
        public int CidadeId { get; set; }

        [Required]
        public int EstadoId { get; set; }

        [MaxLength(100)]
        [Required]
        public string Descricao { get; set; }

        [ForeignKey("EstadoId")]
        public virtual Estado Estado { get; set; }
    }

1 answer

2


Don’t do this:

if (estado == null)
{
    estado = new Estado();
    estado.EstadoId = 43; // <--- Evite isso
    estado.Descricao = "RS";
    context.Estado.Add(estado);
    context.SaveChanges();
}

The primary key definition should be done by the Entity Framework, and not by you. The correct is the search be as follows for your example:

var estado = context.Estado.FirstOrDefault(a => a.Descricao == "RS");

I’m sure the code won’t look like this at the end. It’s just a test.

Another thing is how you use contexts to upload information. By doing this:

using (TesteContext context = new TesteContext())
{ ... }

You are eliminating the context that carries your information when you return the object. Without an active context, the object is not observed by the Entity Framework and considered a new object.

The Controller already possesses in its Dispose the ability to eliminate context at the end of the implementation cycle. Therefore, the construction using need not be used.

Instead, declare the context outside of your methods. As it is not a Controller your case, pass the same context used to insert the City also for the research and insertion of State:

static void Main(string[] args)
{
    var context = new TesteContext();

    var estado = GetEstado(context);

    var cidade = new Cidade();                
    cidade.Estado = estado;
    cidade.Descricao = "SM";
    context.Cidade.Add(cidade);
    context.SaveChanges();
}

static Estado GetEstado(TesteContext context)
{
    var estado = context.Estado.FirstOrDefault(a => a.Descricao == "RS");

    if (estado == null)
    {
        estado = new Estado();
        // estado.EstadoId = 43;
        estado.Descricao = "RS";
        context.Estado.Add(estado);
        context.SaveChanges();
    }

    return estado;
}
  • The difficulty of programmers is to understand that the use of selection by Id should not be done in a human way. Id is a unique, internal identifier of each record of each entity in the system.

  • 1

    I use the state.Estadoid = 43 because it is the IBGE code of the state and it is already related to the city, facilitates in the future when it needs the ibge code of the state in the city, if it is going to leave for the EF the Id, it would have to have a Column Code. the tricky thing is that today I don’t share my context with my classes, which I admit is a mistake I’ll have to correct, each class instance its context, which is why I separated Getestado into another method with another context.

Browser other questions tagged

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