2

Closed

Migrations: Duplicate index created when multiple 1:0..1 associations [FixedIn6.1.0-alpha1] [AffectedLastRTM]

description

Given the following model...
public class SwagBag
{
    public int Id { get; set; }
    public virtual Hat Hat { get; set; }
    public virtual Bracelet Bracelet { get; set; }
}

public class Bracelet
{
    public int Id { get; set; }
    public virtual SwagBag SwagBag { get; set; }
}

public class Hat
{
    public int Id { get; set; }
    public virtual SwagBag SwagBag { get; set; }
}

class Context : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SwagBag>()
            .HasRequired(c => c.Hat).WithOptional(p => p.SwagBag);

        modelBuilder.Entity<SwagBag>()
            .HasRequired(c => c.Bracelet).WithOptional(l => l.SwagBag);
    }
}
...a migration is scaffolded that includes the following statement.
CreateTable(
    "dbo.SwagBags",
    c => new
        {
            Id = c.Int(nullable: false),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.Hats", t => t.Id)
    .ForeignKey("dbo.Bracelets", t => t.Id)
    .Index(t => t.Id)
    .Index(t => t.Id);
As you can see, there are two calls to .Index(t => t.Id). This also affects 1:0..1 associations implied by TPT mapping.
Closed Dec 19, 2013 at 1:13 AM by maumar
Verified, closing

comments

jerone wrote Apr 15, 2013 at 10:06 AM

Please update the StackOverflow question when this issue is fixed.

RoMiller wrote Apr 18, 2013 at 11:01 PM

EF Team Triage: We agree that we should fix this. Taking into account where we are in the EF6 release and that there is a workaround (remove the duplicate call to Index) our team is not planning to fix it in EF6. Therefore, we are moving it to the Future release to reconsider in the next release.

lhmiranda wrote Oct 28, 2013 at 2:03 PM

Just had this problem trying to set two 1:1 associations between subtypes:
public abstract class Company
{
    public int Id { get; set; }
    ...
}

public class Dealer : Company
{
    public DealerFundsAccount FundsAccount { get; set; }
    ...
}

public class Retailer : Company
{
    public RetailerFundsAccount FundsAccount { get; set; }
    ...
}
public abstract class FundsAccount
{
    public int Id { get; set; }
    ...
}

public class DealerFundsAccount : FundsAccount
{
    public Dealer Dealer { get; set; }
    ...
}

public class RetailerFundsAccount : FundsAccount
{
    public Retailer Retailer { get; set; }
    ...
}
public DbSet<Company> Companies { get; set; }
public DbSet<FundsAccount> FundsAccounts { get; set; }
modelBuilder.Entity<Retailer>()
    .HasRequired(r => r.FundsAccount)
    .WithRequiredDependent(rfa => rfa.Retailer);

modelBuilder.Entity<Dealer>()
    .HasRequired(d => d.FundsAccount)
    .WithRequiredDependent(dfa => dfa.Retailer);
Produces:
CreateTable(
            "dbo.FundsAccount",
            c => new
                {
                    Id = c.Int(nullable: false),
                    Discriminator = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Company", t => t.Id)
            .ForeignKey("dbo.Company", t => t.Id)
            .Index(t => t.Id)
            .Index(t => t.Id);

maumar wrote Oct 29, 2013 at 3:17 AM

Bumping to medium pri as more customers hit this issue (see 1773)

BriceLambson wrote Nov 11, 2013 at 6:12 PM

Fixed in changeset 4d11ddbb6d31128842ce624eb408126889b0862c

Mugdhak wrote Nov 15, 2013 at 12:23 AM

This is fixed for this exact scenario, but introduces following issue.

Maurycy and I tried a different variation of this scenario. We had the exact same entities repeated, swagbag2, hat2 and bracelet2. Then we ran thru this same scenario to enable the migrations. It generated the migration fine for Swagbag but not for Swagbag2.
 public override void Up()
        {
            CreateTable(
                "dbo.Foos",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                    })
                .PrimaryKey(t => t.Id);
            
            CreateTable(
                "dbo.SwagBags",
                c => new
                    {
                        Id = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.Bracelets", t => t.Id)
                .ForeignKey("dbo.Hats", t => t.Id)
                .Index(t => t.Id);
            
            CreateTable(
                "dbo.Bracelets",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                    })
                .PrimaryKey(t => t.Id);
            
            CreateTable(
                "dbo.Hats",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                    })
                .PrimaryKey(t => t.Id);
            
            CreateTable(
                "dbo.SwagBag2",
                c => new
                    {
                        Id = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.Bracelet2", t => t.Id)
                .ForeignKey("dbo.Hat2", t => t.Id);
            
            CreateTable(
                "dbo.Bracelet2",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                    })
                .PrimaryKey(t => t.Id);
            
            CreateTable(
                "dbo.Hat2",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                    })
                .PrimaryKey(t => t.Id);
            
        }
Note that in the above generated migration code, Index is added for Swagbag, but not for Swagbag2. This is because we distinct based on Index Name which is IX_<PropertyName>. So if there are more than one indices on the Id columns, it eats all up but the first one. Bumping to HIgh pri.

ajcvickers wrote Dec 2, 2013 at 5:45 PM

Fixed in changeset 806abbd902810fe884acb005b419e371c15c7cee