Auto Relationship in EF

6

I'm having the following problem when creating two auto relationships.

When you run the Update-Database the following error message appears:

  

Unable to determine the main end of an association between the   types 'Autorelação.Franquia' and 'Autorelação.Franquia'. The main   end of this association must be explicitly configured using either the   relationship fluent API or data annotations.

My Class

public class Franquia
    {
        [Key]
        public int FranquiaId { get; set; }

        public int? FranquiaMasterId { get; set; }

        public int? FranquiaSeniorId { get; set; }

        [ForeignKey("FranquiaMasterId")]
        public virtual Franquia FranquiaMaster { get; set; }

        [ForeignKey("FranquiaSeniorId")]
        public virtual Franquia FranquiaSenior { get; set; }
    }

Detail, when running only one auto relationship works perfectly, however with both appears the error.

    
asked by anonymous 28.07.2016 / 15:49

1 answer

9

Following your line of reasoning, a Franquia might have a franchise list, and that's exactly what you're missing when you use DataAnnotations .

For this, you should also use the InverseProperty to perform the proper mapping of navigation properties.

Your code will look like this:

public class Franquia
    {
        [Key]
        public int FranquiaId { get; set; }

        public int? FranquiaMasterId { get; set; }

        public int? FranquiaSeniorId { get; set; }

        [ForeignKey("FranquiaMasterId")]
        public virtual Franquia FranquiaMaster { get; set; }

        [ForeignKey("FranquiaSeniorId")]
        public virtual Franquia FranquiaSenior { get; set; }

        [InverseProperty("FranquiaMaster")]
        public ICollection<Franquia> FranquiasMasters { get; set; }

        [InverseProperty("FranquiaSenior")]
        public ICollection<Franquia> FranquiasSeniors { get; set; }
    }

There is the possibility of doing Fluent API , which would look like this:

modelBuilder.Entity<Franquia>()
    .HasOptional(s => s.FranquiaMaster)
    .WithMany(s => s.FranquiasMasters)
    .HasForeignKey(s => s.FranquiaMasterId);

modelBuilder.Entity<Franquia>()
    .HasOptional(s => s.FranquiaSenior)
    .WithMany(s => s.FranquiasSeniors)
    .HasForeignKey(s => s.FranquiaSeniorId);

If you are using Migrations and it is the creation of the table, and not change, the generated migration will have this code:

public partial class addFranquias : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Franquias",
            c => new
                {
                    FranquiaId = c.Int(nullable: false, identity: true),
                    FranquiaMasterId = c.Int(),
                    FranquiaSeniorId = c.Int(),
                })
            .PrimaryKey(t => t.FranquiaId)
            .ForeignKey("dbo.Franquias", t => t.FranquiaMasterId)
            .ForeignKey("dbo.Franquias", t => t.FranquiaSeniorId)
            .Index(t => t.FranquiaMasterId)
            .Index(t => t.FranquiaSeniorId);

    }

    public override void Down()
    {
        DropForeignKey("dbo.Franquias", "FranquiaSeniorId", "dbo.Franquias");
        DropForeignKey("dbo.Franquias", "FranquiaMasterId", "dbo.Franquias");
        DropIndex("dbo.Franquias", new[] { "FranquiaSeniorId" });
        DropIndex("dbo.Franquias", new[] { "FranquiaMasterId" });
        DropTable("dbo.Franquias");
    }
}

And to complete, you will have the following SQL that will be executed in the database:

CREATE TABLE [dbo].[Franquias] (
    [FranquiaId] [int] NOT NULL IDENTITY,
    [FranquiaMasterId] [int],
    [FranquiaSeniorId] [int],
    CONSTRAINT [PK_dbo.Franquias] PRIMARY KEY ([FranquiaId])
)
CREATE INDEX [IX_FranquiaMasterId] ON [dbo].[Franquias]([FranquiaMasterId])
CREATE INDEX [IX_FranquiaSeniorId] ON [dbo].[Franquias]([FranquiaSeniorId])
ALTER TABLE [dbo].[Franquias] ADD CONSTRAINT [FK_dbo.Franquias_dbo.Franquias_FranquiaMasterId] FOREIGN KEY ([FranquiaMasterId]) REFERENCES [dbo].[Franquias] ([FranquiaId])
ALTER TABLE [dbo].[Franquias] ADD CONSTRAINT [FK_dbo.Franquias_dbo.Franquias_FranquiaSeniorId] FOREIGN KEY ([FranquiaSeniorId]) REFERENCES [dbo].[Franquias] ([FranquiaId])
    
28.07.2016 / 16:26