The declared type of navigation property XYZ is no

2019-04-17 04:47发布

问题:

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);

回答1:

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).



回答2:

Your two models don't agree. In your example, each Template record has 0..1 Employee and 0..1 User. You have multiple records with the same TemplateId, but they're still different records. EF doesn't know how to take all of those records and turn them into a single Template object in memory.

Assuming these are 1-to-many relationships (each Employee can only be in one Template, each User can only be in one template) your foreign keys are on the wrong side. Employee and User should both have TemplateIds.

If you have many-to-many relationships, you will need a new table to represent the association. See associative entity.