Search code examples
c#.netentity-frameworkef-code-firstnavigation-properties

The declared type of navigation property XYZ is not compatible with the result of the specified navigation


Hi There I have the following Model

Template (Id,Name) UserBody (Id, name) EmployeeBody (Id, Name) I then Have a template mappers where i associate a template with one of many users and employess.

TemplatesMaps (id, TemplateId, UserId, EmployeeId) userid and employeeId are nullable

I need a TemplatesMaps to consist of 1 templateid mapping to many Userbody.id 's and many EmployeeBody.Id's Example

Id   TemplateId UserBodyId, EmployeeBodyId
1    1          1           Null
2    1          Null        Null  
3    2          4           Null
4    2          Null        5

MY Code is as follows

  public class UserBody 
  {
    [Key]
    public virtual int Id { get; set; }

    public virtual string Name { get; set; }
  }

  public class EmployeeBody
  {
    [Key]
    public virtual int Id { get; set; }

    public virtual string Name { get; set; }
  }

  public class Template
  {
    [Key]
    public virtual int Id { get; set; }

    public virtual string Name { get; set; }
  }

  public class TemplatesMaps
  {

    [Key]
    public virtual int Id { get; set; }

    public virtual Template Template { get; set; }

    public virtual ICollection<EmployeeBody> Employees { get; set; }

    public virtual ICollection<UserBody> Users { get; set; }
  }

  public class MyDbContext : DbContext
  { 
    public virtual IDbSet<EmployeeBody> EmployeeBody { get; set; }
    public virtual IDbSet<UserBody> UserBody { get; set; }
    public virtual IDbSet<Template> Templates { get; set; }
    public virtual IDbSet<TemplatesMaps> TemplatesMaps { get; set; }



    public MyDbContext() : base("Default")
    {
      Database.SetInitializer<TrawlerDbContext>(null);
    }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      modelBuilder.Entity<TemplatesMaps>().HasOptional(o => o.Employees).WithMany().Map(m => m.MapKey("EmployeeId"));
      modelBuilder.Entity<TemplatesMaps>().HasOptional(o => o.Usersus).WithMany().Map(m => m.MapKey("UserId"));
      base.OnModelCreating(modelBuilder);
    }


    //when i run the following i get the error  The declared type of navigation property XYZ is not compatible with the result of the specified navigation.
    var test = _templateMapperRepo.GetAll().Where(x => x.Template.Id == input.TemplateId).Include(x => x.Users).Include(xx => xx.Employees);

Solution

  • TemplatesMaps (Id, TemplateId, UserId, EmployeeId) looks more like a junction table, thus requires a different entity model:

    public class TemplatesMaps
    {
        [Key]
        public virtual int Id { get; set; }
        public virtual Template Template { get; set; }
        public virtual EmployeeBody Employee { get; set; }
        public virtual UserBody User { get; set; }
    }
    

    and setup

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TemplatesMaps>().HasRequired(o => o.Template).WithMany().Map(m => m.MapKey("TemplateId"));
        modelBuilder.Entity<TemplatesMaps>().HasOptional(o => o.Employee).WithMany().Map(m => m.MapKey("EmployeeId"));
        modelBuilder.Entity<TemplatesMaps>().HasOptional(o => o.User).WithMany().Map(m => m.MapKey("UserId"));
        base.OnModelCreating(modelBuilder);
    }
    

    If needed, you can add reverse navigation property

    public virtual ICollection<TemplatesMaps> TemplateMaps { get; set; }
    

    to any of the Template, UserBody and EmployeeBody classes. Just make sure to update the corresponding WithMany configuration accordingly, i.e. WithMany() => WithMany(e => e.TemplateMaps).