简体   繁体   中英

Entity Framework Core - Migration - No Parameterless Constructor Defined for this Object

I am working with the latest .Net Core and EF Core in Visual Studio 2017. I have created a model and it was working great. I have since made some modifications and am getting the following error when I try to add a new migration:

Build succeeded.
  0 Warning(s)
  0 Error(s)

Time Elapsed 00:00:09.08
System.MissingMethodException: No parameterless constructor defined for this object.
  at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
  at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
  at System.Activator.CreateInstance(Type type, Boolean nonPublic)
  at System.Activator.CreateInstance(Type type)
  at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass12_0.<FindContextTypes>b__3()
  at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 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.<Execute>b__0()
  at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
No parameterless constructor defined for this object.

I have compared my code since the last check in and have commented out certain chunks of code to see if the error persists and whatever I comment out, it still fails with the same error.

Question: Is there a way to get more detailed information on exactly WHAT type does not have a parameterless constructor? Or even run this from within VS and perhaps get a breakpoint?

Update: Based on some of the comments, here is some code.

For the DbContext override

public class AlmanacDb : IdentityDbContext<ApplicationUser, ApplicationRole, int> {

  private readonly ILogger logger;

  public AlmanacDb(DbContextOptions<AlmanacDb> options, ILoggerFactory loggerFactory) : base(options) {
    this.logger = loggerFactory.CreateLogger<AlmanacDb>();
  }

  protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
    optionsBuilder.UseSqlServer("Server=.\\SQLExpress;Database=Almanac;Trusted_Connection=True;MultipleActiveResultSets=True;");
  }

  ...
}

I do have a IDbContextFactory but it is not referenced anywhere and worked without a reference. Not sure if this is a problem or not based on a link provided in the 2nd comment. If memory serves, as long as the IDbContextFactory is within the solution, it should find it?

public class AlmanacDbFactory : IDbContextFactory<AlmanacDb> {

  private IConfigurationRoot configuration;
  private readonly ILoggerFactory loggerFactory;

  public AlmanacDbFactory(ILoggerFactory loggerFactory) {
    var builder = new ConfigurationBuilder()
     .SetBasePath(System.AppContext.BaseDirectory)
     .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

    this.configuration = builder.Build();
    this.loggerFactory = loggerFactory;
  }

  public AlmanacDb Create(DbContextFactoryOptions options) {
    var optionsBuilder = new DbContextOptionsBuilder<AlmanacDb>();
    optionsBuilder.UseSqlServer(
      configuration.GetConnectionString("AlmanacSQL"), m => { m.EnableRetryOnFailure(); }
    );

    return new AlmanacDb(optionsBuilder.Options, loggerFactory);
  }
}

My Startup.cs class

public void ConfigureServices(IServiceCollection services) {
  try {
    services.AddDbContext<AlmanacDb>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("AlmanacSQL"))
    );
    services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

    services.AddIdentity<ApplicationUser, ApplicationRole>()
      .AddEntityFrameworkStores<AlmanacDb, int>()
      .AddDefaultTokenProviders();

    services.AddScoped<SignInManager<ApplicationUser>, AvantiaSignInManager<ApplicationUser>>();

    services.AddAuthorization(x => {
      x.AddPolicy("EmployeeOnly", p => p.RequireClaim("EmployeeNumber"));
    });

    services.AddMvc();
  } catch (Exception e) {
    Console.WriteLine(e.ToString());
    throw;
  }
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, AlmanacDb context) {
  ... // Nothing actually touches the AlmanacDb within this code so I left it out
}

Update 2: Solutiuon Seeing that I am learning ASP.Net Core I am reading a ton of sites (including docs.microsoft.com) at one point I put in the IDbContextFactory code as you can see above. I removed that from my code and the error went away and everything built and created the migration.

I am going to mark @alessalessio as the answer as I assume (have not tested it yet) that taking out the ILoggerFactory loggerFactory dependency within the AlmanacDbFactory constructor will do the trick as well.

Design-time tools attempt to automatically find how your application creates instances of your DbContext type. If EF cannot find a suitable way to initialize your DbContext, you may encounter this error.

Options: 1- Either create a parameterless constructor

  public AlmanacDb() { }
  protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  {           
       optionsBuilder.UseSqlServer(_connString);
  }

  private readonly string _connString = "<your conn string>";

2-

public AlmanacDb Create()
{
     var optionsBuilder = new DbContextOptionsBuilder<AlmanacDb>();
     optionsBuilder.UseSqlServer(connectionString);

     return new AlmanacDb(optionsBuilder.Options);
}

https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext

If you have a separate project for context. set a startup project with the target project

dotnet ef migrations add InitialCreate -s .\src\WebUI\  -p .\src\Infrastructure\ --verbose

I had the same issue. My problem started when i changed my imeplementation of ApplicationUser to User with Guid Id.

public class User : IdentityUser<Guid>

First I started getting some crazy errors and after setting my DbContext to:

public class NgSchoolsContext : IdentityDbContext<User, IdentityRole<Guid>, Guid>

I started getting the "No parameterless constructor" error. What finally fixed it was changing the Roles configuration in Startup:

services.AddIdentityCore<User>() .AddEntityFrameworkStores<NgSchoolsContext>() .AddRoles<IdentityRole<Guid>>() .AddDefaultTokenProviders();

Notice the IdentityRole part. You don't need to implement a thing, just put it like that. It should work out of the box. HOWEVER!! Your migrations WILL fail and you'll have to rebuild your db from start. Entity can't handle the fact that all of his primary keys went from string(or whatever) to Guid and won't be able to update the database. Well, that is at least easier to solve. Drop database, delete all migrations, Add-Migration (new initial) and Update-Database. This would be so easy if for normal error message.

I had the same error "No parameterless constructor defined for type ..." while trying to adda migration. Turns out that when running ef migrations entity framework passes on arguments in the startup project Program.cs The string[] args was removed for security reasons. Adding this resolved the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM