6

この問題の解決策を見つけるのに苦労しています。

MVC4 プロジェクトで EF Code First をセットアップしようとしています。Person から継承する User と Customer があります。次に、Customer と多対多の関係を持ち、User と 1 対多の関係を持つ Template オブジェクトを作成します。設定方法は次のとおりです。

モデル

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

環境

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

コンテキストから Person DBSet を削除すると、これは正常に機能しますが、TPT 継承が設定されます。TPH 継承を使用したいのですが、コンテキストで Person DBSet を使用して移行を有効にすると、次のように停止します。

NavigationProperty 'テンプレート' が無効です。AssociationType 'MvcProject.Models.Template_Customers' の FromRole 'Template_Customers_Target' のタイプ 'MvcProject.Models.Customer' は、この NavigationProperty が宣言されているタイプ 'MvcProject.Models.Person' と正確に一致する必要があります。

ここでどこが間違っていますか?

4

2 に答える 2

14

基本エンティティからナビゲーション プロパティを継承することはできません。それらは常に、関係の反対側が参照しているクラスで宣言する必要があります。

  • Template.CustomersCustomer( ではなくPerson) を参照しているため、逆ナビゲーション プロパティは( ではなく)Templatesで宣言する必要があります。CustomerPerson
  • Template.UserUser( ではなくPerson) を参照しているため、逆ナビゲーション プロパティは( ではなく)Templatesで宣言する必要があります。UserPerson

Templatesしたがって、基本的にコレクションPersonを両方の派生クラスに移動する必要があります。

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

次に、次のように Fluent API を使用して 2 つの関係を定義できます。

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);
于 2013-03-27T20:21:42.637 に答える
0

HasMany セレクターを People に変更します。

    modelBuilder.Entity<Template>()
        .HasMany(x => x.People) // here
        .WithMany(x => x.Templates)
        .Map(x => x.MapLeftKey("TemplateId")
            .MapRightKey("PersonId")
            .ToTable("TemplateCustomer")
        );
于 2013-03-27T17:15:15.163 に答える