-1

I have an old database which has some tables without primary key. Now I'm moving my old project to Asp.Net Core and using Entity Framework Core 2.0.1 Code First approach. I have made the model class of table and trying to add migration using Add-Migration, but it gives the below error. I think technically its expected behavior, But what are other alternative ways so that I don't need to modify the existing table schema.

System.InvalidOperationException: The entity type 'TestTable' requires a primary key to be defined. at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateNonNullPrimaryKeys(IModel model) at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model) at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model) at Microsoft.EntityFrameworkCore.Internal.SqlServerModelValidator.Validate(IModel model) at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator) at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory) at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass22_0.b__0(ServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure1 accessor) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func1 factory) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) The entity type 'TestTable' requires a primary key to be defined.

Model class:

public class TestTable
{
    [StringLength(255)]
    public string Col1 { get; set; }
    [Required]
    public int Col2 { get; set; }
    [Required]
    public int Col3 { get; set; }
    public DateTime? Col4 { get; set; }
    [Required]
    public int Col5 { get; set; }
    [Required]
    public int Col6 { get; set; }
    [Required]
    public int Col7 { get; set; }
}

I have thought one solution like to add an autoincrement identity column as PK. Please suggest a good and proper way to do this?

[Key]
public int Id { get; set; }
Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
  • 1
    Your solution of adding an auto-increment identity column as PK would work very much fine for you as per EF require PK to be able to uniquely identify each record and is very much necessary for insert and update operations. – Tayyab Apr 03 '18 at 09:59
  • Possible duplicate of [Entity Framework: table without primary key](https://stackoverflow.com/questions/3996782/entity-framework-table-without-primary-key) – Tayyab Apr 03 '18 at 10:03
  • 1
    You can try EF Core 2.1 [Query types](https://learn.microsoft.com/en-us/ef/core/modeling/query-types) when released. According to the documentation, one of their usage scenarios are *"Mapping to tables that do not have a primary key defined"* – Ivan Stoev Apr 03 '18 at 10:06
  • @IvanStoev Thanks it will be very useful. Do you have any idea about the release date of EF Core 2.1? – Vivek Nuna Apr 03 '18 at 10:59
  • According to the [Roadmap](https://learn.microsoft.com/en-us/ef/core/what-is-new/roadmap), somewhere in [Q2 2018](https://github.com/aspnet/Home/wiki/Roadmap) – Ivan Stoev Apr 03 '18 at 11:06

1 Answers1

1

In the code file of context:

protected override void OnModelCreating( DbModelBuilder model_builder )
{
    base.OnModelCreating( model_builder );
    model_builder.Entity<TestTable>().HasKey(
        t => new { t.Id }
    );
}

So basically you just need to specify which columns can be primary key.

Kaval Patel
  • 670
  • 4
  • 20