问题
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