EF relationship

Asked

Viewed 101 times

1

I know it’s something basic, but how do I make a relationship between Entities using the Entity Framework?

I have the Competition table and the Competition table. The Competition table must have an associated status (Normal, Cancelled and etc).

Below is the code of the classes:

[Table("Concursos")]
public class Concurso
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Display(Name = "Id")]
    public int Id { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 5)]
    [Display(Name = "Descrição")]
    public string Descricao { get; set; }

    [Required]
    [DataType(DataType.DateTime, ErrorMessage = "A data de cadastro deve ser informada.")]
    [Display(Name = "Data Cadastro")]
    public DateTime DataCadastro { get; set; }

    [Required]
    [DataType(DataType.DateTime, ErrorMessage = "A data de início deve ser informada.")]
    [Display(Name = "Data Início")]
    public DateTime DataInicio { get; set; }

    [DataType(DataType.DateTime)]
    [Display(Name = "Data Fim")]
    public DateTime DataFim { get; set; }

    [Display(Name = "Observacao")]
    [StringLength(500, ErrorMessage = "The {0} deve ter no maximo {1} letras.")]
    public string Observacao { get; set; }

    public int? StatusID { get; set; }

    [ForeignKey("StatusID")]
    public virtual StatusConcursos StatusConcurso { get; set; }

}

public class StatusConcursos
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Display(Name = "Id")]
    public int Id { get; set; }

    [Required]
    [Display(Name = "Descrição")]
    public string Descricao { get; set; }

    public virtual Concurso Concurso { get; set; }

}

The way it is error occurs when I try to create a new Migration. Follow error message:

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

  • Like Concursos relates to StatusConcursos?

  • In the Contests table in the Statusid column you should have the Id for Statusconcursos.

  • The relationship is 1 for many where a Contests can have a Statusconcursos???

2 answers

2


If it is 1 for muitos make the change in StatusConcursos which has a list of Concurso:

[Table("StatusConcursos")]
public class StatusConcursos
{
    public StatusConcursos()
    {
        Concursos = new HashSet<Concurso>();
    }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Display(Name = "Id")]
    public int Id { get; set; }

    [Required]
    [Display(Name = "Descrição")]
    public string Descricao { get; set; }

    public virtual ICollection<Concurso> Concursos { get; set; }

}

Observing: To Concurso does not need any change.

Useful reading:

  • 1

    It worked exactly as I wanted it.

0

Well, first I’ll show you a little bit of how I usually do in my projects when I have the question of Status in certain functionalities.

To carry out the mapping in my projects, I define a history in the main entity, which in your case is the Concurso. Being as follows

    [Table("Concursos")]
    public class Concurso
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Display(Name = "Id")]
        public int Id { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 5)]
        [Display(Name = "Descrição")]
        public string Descricao { get; set; }

        [Required]
        [DataType(DataType.DateTime, ErrorMessage = "A data de cadastro deve ser informada.")]
        [Display(Name = "Data Cadastro")]
        public DateTime DataCadastro { get; set; }

        [Required]
        [DataType(DataType.DateTime, ErrorMessage = "A data de início deve ser informada.")]
        [Display(Name = "Data Início")]
        public DateTime DataInicio { get; set; }

        [DataType(DataType.DateTime)]
        [Display(Name = "Data Fim")]
        public DateTime DataFim { get; set; }

        [Display(Name = "Observacao")]
        [StringLength(500, ErrorMessage = "The {0} deve ter no maximo {1} letras.")]
        public string Observacao { get; set; }
        //histórico de status para o concurso
        public ICollection<ConcursoHistorico> ConcursosHistoricos { get; set; }    
    }

The second part is to define the entity ConcursoHistorico, being as follows

    [Table("ConcursosHistoricos")]
    public class ConcursoHistorico
    {
        public int ConcursoHistoricoId { get; set; }
        public ConcursoStatus Status { get; set; }
        public DateTime Data { get ;set; }
        public string Usuario { get; set; }
        public int ConcursoId { get; set; }
        public virtual Concurso Concurso { get; set; }
    }

and I also have a Enum with possible status

public enum ConcursoStatus
    {
        Normal = 1,
        Cancelado = 2
    }

In this example that I propose, it is defined that the mapping is 1 for many, and a contest will always have several historical. Being the last history entered, the current status of the contest, you can do something of the kind to recover the current status

            using (TesteContext context = new TesteContext())
            {
                var concurso = context.Concursos.Include(a => a.ConcursosHistoricos).FirstOrDefault(a => a.Id == 1);

                var status = concurso.ConcursosHistoricos.OrderBy(a => a.Data).Last();
            }

Look at this one link several examples of mapping

  • Pablo, very interesting this method, I will check if it will be necessary to use this history model.

Browser other questions tagged

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