I'm currently getting the following error during dotnet ef migrations add Initial
Unable to create a 'DbContext' of type ''.
The exception 'The 'TestParent' property 'TestChild.Parent' could not be mapped because the database provider does not support this type.
Consider converting the property value to a type supported by the database using a value converter.
See https://aka.ms/efcore-docs-value-converters for more information.
Alternately, exclude the property from the model using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
My minimum model looks like this:
public class RecipeContext : DbContext
{
public DbSet<TestParent> Parents { get; set; }
public RecipeContext(DbContextOptions<RecipeContext> options)
: base(options) { }
}
[PrimaryKey(nameof(Name))]
public class TestParent
{
[Required]
public string Name { get; set; }
public virtual ICollection<TestChild> Children { get; set; }
}
[PrimaryKey(nameof(Parent))]
public class TestChild
{
[Required]
public virtual TestParent Parent { get; set; }
}
In the real world, TestChild
has a composite primary key, so it does make a bit more sense than this minimal example.
I've tried this with both the Sqlite and SQL Server providers, both provide identical errors, which leads me to believe it's not specific to one provider, and is instead either a 'bug' in EF Core (v8.0.4) or much more likely some misunderstanding of how the navigation linkages / foreign key attributes in EF Core work together.
As long as I don't have the navigation / foreign key member (Parent) within the PrimaryKey
attribute for the TestChild
class, it works. e.g. if I add another column like Id
to TestChild
, and have just this as the PrimaryKey
for TestChild
, it will work.
However this isn't really aligned with the uniqueness constraint I would like. For each Parent
, there can only be a single Child
with the same name (hence in the real world I want PrimaryKey(nameof(Parent),nameof(Name)
).
Any guidance on this would be great. Perhaps there is EF Core doco that describes exactly what I want (and how I'm doing it wrong)?
EF Core works based on the conventions by the default and it can't understand your current setup. By default EF Core will generate a shadow FK for your setup (ParentName
, but note that conventions can change based on the version and setup) and you need to provide it's name to use as PK (not the navigation property name). For example the following works for my minimal setup with SQLite:
[PrimaryKey("ParentName")]
public class TestChild
{
[Required]
public virtual TestParent Parent { get; set; }
}
Or you can explicitly declare the navigation property key:
[PrimaryKey(nameof(ParentName))]
public class TestChild
{
public string ParentName { get; set; }
[Required]
[ForeignKey(nameof(ParentName))]
public virtual TestParent Parent { get; set; }
}
See also: