efcore: Cannot create a unique index / alternate key - and wrong error message is given
I am trying to avoid duplicate entries in a link table.
When I use either HasIndex or HasAlternateKey using a navigation property, not only does EF migrations disallow it, but it gives me a wrong error message (which has led me on a wild goose chase for most of the day).
Source code
Domain classes
public class Parent
{
public Guid Id { get; private set; } = Guid.NewGuid();
public virtual IEnumerable<Child> Children { get; private set; } = new List<Child>();
}
public class Child
{
public Guid Id { get; private set; } = Guid.NewGuid();
public virtual Parent Parent { get; set; } = null!;
public string Name { get; set; } = "";
}
ApplicationDbContext
internal class ApplicationDbContext : DbContext
{
public DbSet<Child> Children { get; set; } = null!;
public DbSet<Parent> Parents { get; set; } = null!;
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
base.OnConfiguring(options);
options.UseSqlServer(
connectionString: @"Server=.\SQLExpress;Database=StevenTCramerSmells;Trusted_Connection=Yes;",
x => x.EnableRetryOnFailure());
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Parent>(x =>
{
x.HasMany(x => x.Children).WithOne(x => x.Parent);
});
modelBuilder.Entity<Child>(x =>
{
// See notes for why these lines are commented out.
// x.Property(x => x.Parent)
// .HasColumnName(nameof(Child.Parent))
// .IsRequired()
// .HasColumnType("uniqueidentifier");
x.HasIndex(x => new { x.Parent, x.Name }).IsUnique();
});
}
}
csproj file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
The error message I see is
‘Parent’ cannot be used as a property on entity type ‘Child’ because it is configured as a navigation.
This has led me to believe my problem is the C# property Parent on the Child class - but it is nothing to do with that. It is the Parent shadow property that is being added by the index.
So my ticket has two parts
1: Could the message be changed to something like “Failed to add shadow property ‘Parent’ on entity type ‘Child’ when creating an index, because a shadow property named Parent has already been defined as a navigation property”
2: How do I ensure uniqueness in my link table by combining the Parent and OtherTable columns into a unique index?
Notes
Please note that I considered whether or not this issue is a duplicate of #11336 or not, but decided it wasn’t because of the following reasons.
A: This ticket asks for the error message to be changed to make it clear the problem is not with the Child.Parent property the application source code, but a shadow-property issue, and that the message should say it is the index/alternate key causing the problem (showing the index name would be fantastic)
B: I tried the solution proposed in that ticket and it did not solve the issue in this case. See the commented out lines in ApplicationDbContext above.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 15 (2 by maintainers)
@GioviQ I’ve standardised on XId instead and it works, thank you!
I think the error message needs to be more helpful, though.