web-dev-qa-db-ja.com

Entity FrameworkCore-移行-このオブジェクトに対してパラメーターなしのコンストラクターが定義されていません

Visual Studio2017で最新の.NetCoreとEFCoreを使用しています。モデルを作成しましたが、うまく機能していました。その後、いくつかの変更を加えましたが、新しい移行を追加しようとすると、次のエラーが発生します。

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.

前回のチェックイン以降にコードを比較し、コードの特定のチャンクをコメントアウトして、エラーが続くかどうかを確認しました。コメントアウトしても、同じエラーで失敗します。

質問:パラメーターなしのコンストラクターがないタイプについて、より詳細な情報を取得する方法はありますか?または、これをVS内から実行して、ブレークポイントを取得することもできますか?

更新:いくつかのコメントに基づいて、ここにいくつかのコードがあります。

DbContextオーバーライドの場合

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;");
  }

  ...
}

私はIDbContextFactoryを持っていますが、どこにも参照されておらず、参照なしで機能します。これが問題であるかどうかは、2番目のコメントで提供されているリンクに基づいてはわかりません。メモリが機能する場合、IDbContextFactoryがソリューション内にある限り、それを見つける必要がありますか?

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);
  }
}

私のStartup.csクラス

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
}

更新2:解決策 ASP.Net Coreを学習しているのを見て、ある時点で大量のサイト(docs.Microsoft.comを含む)を読んでいます。IDbContextFactoryコードを次のように入力しました。あなたは上を見ることができます。それをコードから削除すると、エラーがなくなり、すべてがビルドされて移行が作成されました。

AlmanacDbFactoryコンストラクター内のILoggerFactory loggerFactory依存関係を取り除くことで同様にうまくいくと私が想定しているように(まだテストしていません)、@ alessalessioを答えとしてマークします。

7
Grandizer

設計時ツールは、アプリケーションがDbContextタイプのインスタンスを作成する方法を自動的に見つけようとします。 EFがDbContextを初期化する適切な方法を見つけられない場合、このエラーが発生する可能性があります。

オプション:1-パラメータなしのコンストラクタを作成する

  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

8
alessalessio

私も同じ問題を抱えていました。私の問題は、ApplicationUserの実装をGUIDIDを持つユーザーに変更したときに始まりました。

_public class User : IdentityUser<Guid>_

最初に私はいくつかのクレイジーなエラーを受け取り始め、DbContextを次のように設定した後:

_public class NgSchoolsContext : IdentityDbContext<User, IdentityRole<Guid>, Guid>_

「パラメーターなしのコンストラクターがありません」というエラーが発生し始めました。最終的に修正されたのは、スタートアップの役割構成を変更することでした。

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

IdentityRoleの部分に注目してください。何かを実装する必要はありません。そのように配置するだけです。箱から出して動作するはずです。しかしながら!!移行は失敗し、データベースを最初から再構築する必要があります。エンティティは、すべての主キーが文字列(またはその他)からGuidに移行し、データベースを更新できないという事実を処理できません。まあ、それは少なくとも解決するのが簡単です。データベースを削除し、すべての移行、Add-Migration(新しいイニシャル)およびUpdate-Databaseを削除します。通常のエラーメッセージの場合、これはとても簡単です。

1
Cubelaster