R
R
Ruslan2019-04-08 14:26:42
C++ / C#
Ruslan, 2019-04-08 14:26:42

How to set up relationships between tables in EntityFramework that refer to each other by foreign key?

Hello!
There are two tables in the database for which two classes are created in the code:

public class ForumTopic
{
        [Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
        public int TopicId { get; set; }
        public int LastMessageId { get; set; }
        [ForeignKey("LastMessageId")]
        public virtual ForumMessage LastMessage { get; set; }
}

public class ForumMessage
{
        [Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
        public int MessageID { get; set; }
        public int TopicID { get; set; }
        [ForeignKey("TopicID")]
        public virtual ForumTopic Topic { get; set; }
}

At first glance, the structure contains links to each other and it is not clear which table is the main table and which is the subordinate table.
Let me explain the meaning: There is a forum topic (ForumTopic), which has a lot of messages (ForumMessage), this relation is set by the field [ForeignKey("TopicID")] public virtual ForumTopic Topic { get; set; }. And the forum topic has a link to the topic's last message, which is set by the LastMessageId and LastMessage fields. (redundancy added to increase performance when generating a list of topics indicating which message was the last one)
When I try to extract something from the EF context, I get an error:
"Unable to determine the principal end of an association between the types 'Common.ForumTopic' and 'Common.ForumMessage'. The principal end of this association must be explicitly configured using either the relationship fluent API or data
annotations structure), how to still set up the EF context so that it, EF works without errors.
Thank you.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
Ruslan, 2019-04-08
@Razbezhkin

Thanks Fat Lorrie for the tip.
Indeed, without specifying a reference to the collection of records in the child table in the form of such a property:
public virtual ICollection Messages { get; set; }
EF couldn't figure out what relationship these two tables had.
but this was not enough, because. there was still an ambiguity that I managed to resolve using the InversePropertyAttribute attribute, which I added before this very property.
As a result, the class structure became like this:

public class ForumTopic
{
        [Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
        public int TopicId { get; set; }
        public int LastMessageId { get; set; }
        [ForeignKey("LastMessageId")]
        public virtual ForumMessage LastMessage { get; set; }
        [InverseProperty("Topic")]
        public virtual ICollection<ForumMessage> Messages { get; set; }
}

public class ForumMessage
{
        [Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
        public int MessageID { get; set; }
        public int TopicID { get; set; }
        [ForeignKey("TopicID")]
        public virtual ForumTopic Topic { get; set; }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question