The derived type 'UserRole' cannot have KeyAttribute on property 'Id' since primary key can only be declared on the root type
See original GitHub issueHi everyone!
Steps to reproduce
- Create ASP.NET Core application from yo generator-aspnetcore-spa with ‘Angular 2’ template (for example, with name ‘Web.Client.Spa’).
- Create .NET Core class library project (for example, with name ‘Core.DAL.Real.Database’) for EF DbContext (and create in this project EF DbContext).
- Create .NET Core class library project for domain models (for example, ‘Core.DomainModels’ and ‘Core.DomainModels.Identity’ - first project for domain models classes and second project for the ASP.NET Identity models [for EF CodeFirst approach]).
In project ‘Core.DomainModels’ add this file: IEntity.cs:
public interface IEntity<T>
{
T Id { get; set; }
}
public interface IEntity : IEntity<Guid>
{
}
And in project ‘Core.DomainModels.Identity’ add this classes:
Abstract & interfaces: IUser.cs
public interface IUser<T> : IEntity<T>
{
DateTime RegisterDate { get; set; }
}
public interface IUser : IUser<Guid>
{
}
IRole.cs
public interface IRole<T> : IEntity<T>
{
string Name { get; set; }
}
public interface IRole : IRole<Guid>
{
}
IUserRole.cs
public interface IUserRole<T>// : IEntity<T>
{
T UserId { get; set; }
T RoleId { get; set; }
IUser User { get; set; }
IRole Role { get; set; }
}
public interface IUserRole : IUserRole<Guid>
{
}
Real models: User.cs
public class User : IdentityUser<Guid>, IUser<Guid>
{
public static User CreateEmptyInstance()
{
return new User();
}
#region Implementation of IUser<Guid>
public DateTime RegisterDate { get; set; }
#endregion
[NotMapped]
public bool IsAuthenticated { get; set; }
}
Role.cs
public class Role : IdentityRole<Guid>, IRole<Guid>
{
}
UserRole.cs
public class UserRole : IdentityUserRole<Guid>, IUserRole
{
#region Implementation of IEntity<Guid>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
#endregion
#region Implementation of IUserRole<Guid>
[NotMapped]
public IUser User { get; set; }
[NotMapped]
public IRole Role { get; set; }
#endregion
}
- Add packages ASP.NET Identity, EF Core (with Tools and Design), Npgsql to MVC App (I’m used PostgreSQL database).
- Add packages EF Core (with Tools) to Core.DAL.Real.Database project.
- In Package Manager Console run command (for startup project Core.DAL.Real.Database):
Add-Migration InitDev -Context EfDbMigrations -Environment Development
- …And I have an error:
System.InvalidOperationException: The derived type 'UserRole' cannot have KeyAttribute on property 'Id' since primary key can only be declared on the root type. at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.KeyAttributeConvention.Apply(InternalModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelBuilt(InternalModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.LazyRef`1.get_Value()
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.TransientCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.TransientCallSite.Invoke(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.EntityFrameworkCore.Design.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Tools.Cli.MigrationsAddCommand.Execute(CommonOptions commonOptions, String name, String outputDir, String context, String environment, Action`1 reporter)
at Microsoft.EntityFrameworkCore.Tools.Cli.MigrationsAddCommand.<>c__DisplayClass0_0.<Configure>b__0()
at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
at Microsoft.EntityFrameworkCore.Tools.Cli.Program.Main(String[] args)
The derived type 'UserRole' cannot have KeyAttribute on property 'Id' since primary key can only be declared on the root type.
My project.json in Core.DAL.Real.Database project:
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"Microsoft.EntityFrameworkCore": "1.0.1",
"Microsoft.EntityFrameworkCore.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
},
"Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.1",
"System.Linq": "4.1.0",
"Core.DomainModels.Identity": "1.0.0-*",
"Core.DomainModels": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
}
}
The issue
The KeyAttribute on property Id in my UserRole class must not throw this error, right? Or I do something wrong?
I found the same issue #5898 but that issue is closed by @AndriySvyryd and appropriate changes (by commit https://github.com/aspnet/EntityFramework/commit/5ce5b86d37859a1410d9e343489f8b2d3fbb9527) are included in 1.0.1 version of EF Core which I used. I’m confused because of this error. And because of this, I cannot create my first (init) migration…
Please help solve this problem…
Further technical details
EF Core version: 1.0.1 Operating system: Windows 10 Visual Studio version: VS 2015 Update 3
Issue Analytics
- State:
- Created 7 years ago
- Comments:12 (6 by maintainers)
@Cubelaster Something like this:
@Cubelaster Avoid using the base type in
OnModelCreating
if you don’t want it included in the model.