EF Core - navigational property in index

随声附和 提交于 2019-12-08 20:50:26

问题


I have the following two classes

public class Tip
{
    public string Home { get; set; }
    public string Away { get; set; }
    public string Prediction { get; set; }
    public Tipster Tipster { get; set; }
    ... other properties
}


public class Tipster
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string Platform { get; set; }
}

Now, I want to make unique index in theTip table. According to the EF Core documentation, there is no Data Annotations syntax, so I am using the fluent one:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Tip>()
            .HasIndex(entity => new { entity.Tipster, entity.Home, entity.Away, entity.Prediction })
            .HasName("IX_UniqueTip")
            .IsUnique();
    }

Now, when I update the database I get the following error

C:..>dotnet ef database update System.InvalidOperationException: Cannot call Property for the property 'Tipster' on entity type 'Tip' because it is configured as a navigation property. Property can only be used to configure scalar properties.

It seems that EF didn't liked the fact that I am using referential property in the index. How can I fix that ?


回答1:


You can't use navigation property in index defining expression. Instead, you should use the corresponding FK property.

The problem in your case is that you don't have explicit FK property in your model Tip. By convention EF Core will create int? TipsterId shadow property. So theoretically you should be able to use EF.Property method to access it:

.HasIndex(e => new { TipsterId = EF.Property<int>(e, "TipsterId"), e.Home, e.Away, e.Prediction })

Unfortunately this doesn't work currently (EF Core 2.0.1). So you have to resort to HasIndex overload with params string[] propertyNames:

.HasIndex("TipsterId", nameof(Tip.Home), nameof(Tip.Away), nameof(Tip.Prediction))



回答2:


They way you defined your entities EF will put the referential column into the tipster table, since it looks like a 1-n relationship. Meaning a tipster can place several tips, but each tip is only placed by a single tipster.

That means on the database level there is nothing to index. No column, no key - nothing.

To fix this you might ask yourself what you really want to achieve with an index in the first place. An index is supposed to make queries using the columns of the index faster and avoid a full table scan.




回答3:


You must define the property TipsterId explicitly cause the Navigation property define it as shadow, so you cannot use it on custom index or alternate key

public class Tip
{
    public string Home { get; set; }
    public string Away { get; set; }
    public string Prediction { get; set; }

    public int TipsterId { get; set; }

    public Tipster Tipster { get; set; }
    ... other properties
}

Now you can

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Tip>()
        .HasIndex(entity => new { entity.TipsterId, entity.Home, entity.Away, entity.Prediction })
        .HasName("IX_UniqueTip")
        .IsUnique();
}


来源:https://stackoverflow.com/questions/47927276/ef-core-navigational-property-in-index

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!