nightingale2k1
nightingale2k1

Reputation: 10335

EntityFramework Core 2.2 to 3.1.1 Got error

I just finished upgrade my .net core 2.2 to 3.1.101 When I run (dotnet run) I got this error on my controllers

Unable to determine the relationship represented by navigation property 'UserAssignment.Appointee' of type 'User'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

Let me explain the relationship first, a User can have many UserAssignment, each UserAssignment can have Appointee and Manager (which is other User).

UserAssignment

namespace CRSApp.API.Models
{
    public class UserAssignment
    {
        public int UserId { get; set; }
        public User User { get; set; }
        public DateTime StartDate {get; set;}
        public bool IsPersonalInsolvency { get; set; }
        public bool IsCorporateInsolvency { get; set; }
        public int? AppointeeId { get; set; }
        public User Appointee { get; set; }
        public int? ManagerId { get; set; }
        public User Manager { get; set; }
        public int? StaffDefaultRateId {get; set;}
        public StaffDefaultRate StaffDefaultRate { get; set; }
    }
}

User.cs

public class User
        {
            public int Id { get; set; }
            [Column(TypeName = "varchar(200)")]
            public string Username { get; set; }
            [Column(TypeName = "blob")]
            public byte[] PasswordHash { get; set; }
            [Column(TypeName = "blob")]
            public byte[] PasswordSalt { get; set; }
            [Column(TypeName = "varchar(200)")]
            public string FirstName { get; set; }

            [Column(TypeName = "varchar(200)")]
            public string LastName { get; set; }

            [Column(TypeName = "varchar(200)")]
            public string MiddleName { get; set; }

            [Column(TypeName = "varchar(200)")]
            public string Email { get; set; }       
            public string MobileNumber { get; set; }       

            public ICollection<UserAssignment> Assignments {get; set;}

        }

the DbContext model builder :

    builder.Entity<UserAssignment>().HasKey(x => new {x.UserId, x.StaffDefaultRateId});
    builder.Entity<UserAssignment>()
        .HasOne( x => x.User)
        .WithMany(y => y.Assignments)
        .HasForeignKey( x => x.UserId);
    builder.Entity<UserAssignment>()
        .HasOne( x => x.StaffDefaultRate)
        .WithMany( y => y.Assignments)
        .HasForeignKey( x => x.StaffDefaultRateId);

Please help me how to solve this problem ? as in the previous ef core 2.2, this code work fine.

Upvotes: 2

Views: 1438

Answers (2)

Ivan Stoev
Ivan Stoev

Reputation: 205789

Apparently bug (something has been broken while fixing something else).

Looks like having two not explicitly mapped reference navigation properties to User (Manager and Appointee) is confusing EF Core 3.1 conventional relationship mapper.

Adding

builder.Entity<UserAssignment>()
    .HasOne(x => x.Appointee);

or

builder.Entity<UserAssignment>()
    .HasOne(x => x.Manager);

will fix it, but to avoid future issues like this, I would suggest explicitly mapping at least the intended relationship navigation properties:

builder.Entity<UserAssignment>()
    .HasOne(x => x.Appointee)
    .WithMany();
builder.Entity<UserAssignment>()
    .HasOne(x => x.Manager)
    .WithMany();

Upvotes: 2

vernou
vernou

Reputation: 7610

https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#conventions

According to the conventions, your code is correct.

https://github.com/dotnet/efcore/issues/13274#issuecomment-420322267

The convention is used only on entities in the context. Add DbSet<UserAssignment> in your context can work.

Or you can specify the foreign key :

builder.Entity<UserAssignment>()
    .HasOne( x => x.Appointee)
    .HasForeignKey( x => x.AppointeeId);
builder.Entity<UserAssignment>()
    .HasOne( x => x.Manager)
    .HasForeignKey( x => x.ManagerId);

Upvotes: 2

Related Questions