Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read
Q&A

How to refer to the same class twice from one Entity Framework entity?

+1
−0

I have two classes, Contestant and Picture, with the following setup:

public class Contestant 
{
    ...
    public int AvatarID { get; set; }

    [ForeignKey(nameof(AvatarID))]
    public virtual Picture? Avatar { get; set; }

    public virtual ICollection<Picture>? Pictures { get; set; }
    ...
}

public class Picture
{
    ...
    public int ContestantID { get; set; }

    [ForeignKey(nameof(ContestantID))]
    public virtual Contestant? Contestant { get; set; }
    ...
}

Each contestant instance has a set of pictures and a single picture from the set that serves as their avatar.

The original setup (without AvatarID or Avatar relationship) worked fine. After adding the Avatar field and relationship, I get a run-time error message when I try to load either the Contestant set or Picture set. It reads:

System.InvalidOperationException: 'Unable to determine the relationship represented by navigation 'Contestant.Avatar' of type 'Picture.' Either manually configure the relationship, or ignore this property using the '[NotMapper]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.'

From my research, this happens when a class refers to another class twice. The answers I saw all involved the same class having both keys of the relationship. For example, a Project class might have multiple employees assigned, one as ProjectEngineer the other as AssignedDeveloper. For those, defining the [ForeignKey()] in the same file worked. I do not know what I need to do, here or possibly in the DbContext's OnModelCreating method.

Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+1
−0

I tried to replicate your case and the only workable solution I could find is to use OnModelCreating configuration (fluent style) instead of attributes:

public class Contestant 
{
	public int Id { get; set; }

	public int AvatarID { get; set; }

	public virtual Picture? Avatar { get; set; }

	public virtual ICollection<Picture>? Pictures { get; set; }
}


public class Picture
{
	public int Id { get; set; }

	public int ContestantID { get; set; }

	public virtual Contestant? Contestant { get; set; }

	public virtual Contestant? ContestantInverse { get; set; }
}


modelBuilder.Entity<Contestant>()
	.HasOne(u => u.Avatar)
	.WithOne(r => r.Contestant)
	.HasForeignKey<Contestant>(u => u.AvatarID)
	.HasConstraintName("FK_Contestant_Avatar")
	.OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Picture>()
	.HasOne(d => d.ContestantInverse)
	.WithMany(p => p.Pictures)
	.HasConstraintName("FK_Picture_Contestant")
	.OnDelete(DeleteBehavior.Restrict);

The Picture needs two navigation properties related to Contestant since it has two relations with it (1:1 and n:1).

As a side note, while liking the attributes more, I decided to use the fluent syntax only because some configurations are not supported by the attributes (e.g. index on 2+ properties), and having the configuration split in two can lead to confusion.

Why does this post require moderator attention?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »