Asp.net mvc 4 实体框架代码首先是多对多关系和继承

Asp.net mvc 4 实体框架代码首先是多对多关系和继承,asp.net-mvc-4,ef-code-first,entity-framework-5,Asp.net Mvc 4,Ef Code First,Entity Framework 5,请原谅,如果这个问题在什么地方得到了回答,我一直很难找到解决这个问题的办法 我试图在MVC4项目上首先设置EF代码。我有一个从Person继承的用户和客户。然后我有一个模板对象,它与客户有多对多关系,与用户有一对多关系。以下是我如何设置它的: 型号 public class Person { [Key] public int PersonID { get; set; } public string LastName { get; set; } public st

请原谅,如果这个问题在什么地方得到了回答,我一直很难找到解决这个问题的办法

我试图在MVC4项目上首先设置EF代码。我有一个从Person继承的用户和客户。然后我有一个模板对象,它与客户有多对多关系,与用户有一对多关系。以下是我如何设置它的:

型号

public class Person
{
    [Key]
    public int PersonID { get; set; }

    public string LastName { get; set; }
    public string FirstName { get; set; }

    public string FullName
    {
        get
        {
            return String.Format("{0} {1}", FirstName, LastName);
        }
    }

    public string Email { get; set; }

    public virtual List<Template> Templates { get; set; }
}

public class User : Person
{
    .... 
}

public class Customer : Person
{
    ....
}

public class Template
{
    public int TemplateId { get; set; }
    public string TemplateName { get; set; }

    public virtual List<Customer> Customers { get; set; }

    [ForeignKey("User")]
    public int UserId { get; set; }
    public virtual User User { get; set; }
}
公共类人物
{
[关键]
公共int PersonID{get;set;}
公共字符串LastName{get;set;}
公共字符串名{get;set;}
公共字符串全名
{
得到
{
返回String.Format(“{0}{1}”,FirstName,LastName);
}
}
公共字符串电子邮件{get;set;}
公共虚拟列表模板{get;set;}
}
公共类用户:Person
{
.... 
}
公共类客户:个人
{
....
}
公共类模板
{
public int TemplateId{get;set;}
公共字符串TemplateName{get;set;}
公共虚拟列表客户{get;set;}
[外键(“用户”)]
public int UserId{get;set;}
公共虚拟用户用户{get;set;}
}
上下文

public class ProjectContext : DbContext
{
    public ProjectContext()
        : base("name=ProjectDB")
    {
    }

    public DbSet<Template> Templates { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions
            .Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Template>()
            .HasMany(x => x.Customers)
            .WithMany(x => x.Templates)
            .Map(x => x.MapLeftKey("TemplateId")
                .MapRightKey("PersonId")
                .ToTable("TemplateCustomer")
            );
    }
}
公共类ProjectContext:DbContext
{
公共项目上下文()
:base(“name=ProjectDB”)
{
}
公共数据库集模板{get;set;}
公共数据库集用户{get;set;}
公共数据库集客户{get;set;}
公共数据库集人物{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions
.Remove();
modelBuilder.Entity()
.HasMany(x=>x.Customers)
.WithMany(x=>x.Templates)
.Map(x=>x.MapLeftKey(“模板ID”)
.MapRightKey(“PersonId”)
.ToTable(“模板客户”)
);
}
}
如果我将persondbset从上下文中移除,这可以正常工作,但会设置TPT继承。我希望使用TPH继承,但当我在上下文中启用Person DBSet的迁移时,它会阻塞:

NavigationProperty“模板”无效。关联类型“MvcProject.Models.Template\u Customers”中来自角色“Template\u Customers\u Target”的类型“MvcProject.Models.Customer”必须与声明此NavigationProperty的类型“MvcProject.Models.Person”完全匹配


我哪里出错了?

将您的HasMany选择器更改为People:

    modelBuilder.Entity<Template>()
        .HasMany(x => x.People) // here
        .WithMany(x => x.Templates)
        .Map(x => x.MapLeftKey("TemplateId")
            .MapRightKey("PersonId")
            .ToTable("TemplateCustomer")
        );
modelBuilder.Entity()
.HasMany(x=>x.People)//这里
.WithMany(x=>x.Templates)
.Map(x=>x.MapLeftKey(“模板ID”)
.MapRightKey(“PersonId”)
.ToTable(“模板客户”)
);
您不能从基本实体继承导航属性。它们必须始终在关系的另一端引用的类中声明

  • 模板。客户
    指的是
    客户
    (而不是
    个人
    ),因此必须在
    客户
    中声明反向导航属性
    模板
    (而不是
    个人
  • 模板。用户
    指的是
    用户
    (而不是
    ),因此必须在
    用户
    中声明反向导航属性
    模板
    (而不是
因此,基本上您必须将
模板
集合从
个人
移动到两个派生类中:

public class Person
{
    // no Templates collection here
}

public class User : Person
{
    //... 
    public virtual List<Template> Templates { get; set; }
}

public class Customer : Person
{
    //...
    public virtual List<Template> Templates { get; set; }
}
公共类人物
{
//这里没有模板集合
}
公共类用户:Person
{
//... 
公共虚拟列表模板{get;set;}
}
公共类客户:个人
{
//...
公共虚拟列表模板{get;set;}
}
然后,您可以使用Fluent API定义两种关系,如下所示:

modelBuilder.Entity<Template>()
    .HasMany(t => t.Customers)
    .WithMany(c => c.Templates) // = Customer.Templates
    .Map(x => x.MapLeftKey("TemplateId")
               .MapRightKey("PersonId")
               .ToTable("TemplateCustomer"));

modelBuilder.Entity<Template>()
    .HasRequired(t => t.User)
    .WithMany(u => u.Templates) // = User.Templates
    .HasForeignKey(t => t.UserId);
modelBuilder.Entity()
.HasMany(t=>t.Customers)
.WithMany(c=>c.Templates)/=Customer.Templates
.Map(x=>x.MapLeftKey(“模板ID”)
.MapRightKey(“PersonId”)
.ToTable(“模板客户”);
modelBuilder.Entity()
.HasRequired(t=>t.User)
.WithMany(u=>u.Templates)/=User.Templates
.HasForeignKey(t=>t.UserId);

要做到这一点,我必须将我的客户名单更改为个人名单。这会破坏目的,我需要与模板和人员建立多对多关系。