4

I have an entity User that has two properties CreatedBy and UpdatedBy both referencing User. By default, EF assumes that these two as a one to one relation to each other. I get the following error message:

Message: System.InvalidOperationException : The child/dependent side could not be determined for the one-to-one relationship that was detected between 'User.CreatedBy' and 'User.UpdatedBy'. To identify the child/dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship configure them without specifying the inverse. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details.

Currently, I have a class like this:

public class User
{

    public int Id { get; set; }

    public int? CreatedById { get; set; }
    public User CreatedBy { get; set; }

    public int? UpdatedById { get; set; }
    public User UpdatedBy { get; set; }

}

Basically, here is what I am trying:

  • The created and updated would have no relation to each other (no navigation/inverse property needed)
  • Any number of users can have the same CreatedBy and any number of users can have the same UpdatedBy.

How can I ask EF to just ignore the navigation property? The main reason I have CreatedBy is so I can use Include(u => u.CreatedBy) later on. I know using IEnumerable<User> AllCreatedUsers property would solve this but I did not want to create an IEnumerable for each in my entity. Is there any way to do this with fluent API?

Here is what I tried:

modelBuilder.Entity<User>()
                .Property<IEnumerable<User>>("AllCreatedUsers");

modelBuilder.Entity<User>().HasOne(u => u.CreatedBy)
                                .WithMany(u => EF.Property<IEnumerable<User>>(u, "AllCreatedUsers"));
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79

2 Answers2

5

You need to configure two Single Navigation Property relationships by using parameterless WithMany method overload:

modelBuilder.Entity<User>()
    .HasOne(u => u.CreatedBy)
    .WithMany();

modelBuilder.Entity<User>()
    .HasOne(u => u.UpdatedBy)
    .WithMany(); 
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • I had tried this earlier. I even tried it with copy-pasting your code. It's still the same result – Neville Nazerane May 12 '18 at 16:48
  • All I can say is that this is the way to deal with such model. If you create a clean new project, copy/paste the `User` class from the question and the fluent configuration from the answer, you will see that it works. – Ivan Stoev May 12 '18 at 16:56
  • Yep, just tested, it worked fine on a clean project. However, there might be some special case(s) this doesn't consider. @vivek's code seems to work in both cases though. – Neville Nazerane May 12 '18 at 17:30
  • This doesn't make any sense to me. FKs are really unrelated to the issue (I could have included them in the fluent setup if they were not matching the convention), and data annotations are absolutely unnecessary (I would say obsolete) in EF Core. – Ivan Stoev May 12 '18 at 17:50
3

You ForeignKey data annotation for both the properties.

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

    public int? CreatedById { get; set; }
    [ForeignKey("CreatedById")]
    public User CreatedBy { get; set; }

    public int? UpdatedById { get; set; }
    [ForeignKey("UpdatedById")]
    public User UpdatedBy { get; set; }
}
Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197