web-dev-qa-db-ja.com

エンティティタイプ 'IdentityUserLogin <string>'では、プライマリキーを定義する必要があります

linuxでdotnet core 1.1を使用しています。startup.cs-> configureで次の行を実行するたびに、通常のdbContextからidentityContextを分割するときに問題が発生します。

//... some other services
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
    serviceScope.ServiceProvider.GetService<ApplicationDbContext>().Database.Migrate();
    //running other database.migrations here + seeding data. But it is the line above that causes problems

そのため、この行は例外をスローします:エンティティタイプ 'IdentityUserLogin'では、定義されるプライマリキーが必要です

私は単にこれを理解していません、なぜIdentityUserLoginにプライマリキーを与えるのが私の仕事ですか??、それはサードパーティのクラスであり、私も触れていません。次の簡単なセットアップがあります。

namespace EsportshubApi.Models
{
    public class ApplicationDbContext :  IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
        }

        public ApplicationDbContext()
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);


        }
    }
}

そしてapplicationUser:

namespace EsportshubApi.Models.Entities
{

    public class ApplicationUser : IdentityUser
    {
        public ApplicationUser() { }

        public static ApplicationUserBuilder Builder()
        {
            return new ApplicationUserBuilder(new ApplicationUser());
        }

        public int AccountId { get; set; }
        public Guid AccountGuid { get; set; }
        public string Salt { get; set; }
        public bool Verified { get; set; }
        public string Checksum { get; set; }
        public string Password { get; set; }
        public DateTime Created { get; set; }
        public DateTime Updated { get; set; }
    }

}

私のスタートアップでは、次の方法でIDフレームワークを構成しています。

configureServices:

services.AddEntityFrameworkSqlServer().AddMySQL().AddDbContext<ApplicationDbContext>(options =>
                    options.UseMySQL(config["ConnectionStrings:DefaultConnection"]));

そして

構成:

 app.UseIdentity();

私のプロジェクトは次の場所でオープンソース化されています: my github repo

それが役立つ場合。

私は多くのことを試しました。最も有望な2つは、このジェネリックショーで使用されるすべてのクラスを導出し、それらを明示的に渡して、すべてのキーをintなどに変更しようとしたことです。それは、int文字列。私が試した他の方法は、OnModelCreatingの内部で次のようにしてIdentityUserLoginに主キーを与えることです:

 modelBuilder.Entity<IdentityUserLogin<int>>()
            .Property(login => login.UserId)
            .ForMySQLHasColumnType("PK")
            .UseSqlServerIdentityColumn()
            .UseMySQLAutoIncrementColumn("AI");

ご覧のとおり、UserIdを整数として持っていたときに戻ってきましたが、UserIdをprimaryKeyにする必要があるかどうかさえわかりません。私はこれの代わりに他のエラーを受け取ることができます

IdentityUserLoginは階層の一部であり、識別値はありません

しかし、ディスクリミネーター値があれば、最終的にはこのエラーに戻ります。私が思う最も奇妙な部分は、UnicornStore githubの例とまったく同じ実装を持っていることです。この例では、アイデンティティフレームワークも少し使用しています。だから、本当に助けが必要です。プロジェクトをダウンロードし、default.appsettings.jsonappsettings.jsonにコピーし、有効な接続文字列dotnet restoreを入れて、dotnet run --environment Developmentで実行すると、このエラーを再現できます。

MySQLの代わりにMSSQLデータベースを使用するように実装を変更しようとしましたが、まったく同じエラーが発生しました。

17
DenLilleMand

iDテーブルのキーはOnModelCreatingIdentityDbContextメソッドにマッピングされます。このメソッドが呼び出されない場合、最終的にエラーが発生します。

あなたがする必要があるのは電話です。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  base.OnModelCreating(modelBuilder);
}

元の回答(念のため、他の参照用にコピーしたもの) here

62
immirza

はい。それで、私はそれを乗り越えたので、私は自分の質問に答えようとします。 OPのgithubリンクをたどって、エラーが発生したプロジェクトを確認することはまだ可能です。

主に間違っていたことは、ApplicationDbContext : IDentityContextしかし、実際には、そのアプリケーションで移行を実行しようとしたときに、アプリケーションの他のdbContextに基づいてエラーがスローされました。私はまだ他のDbContextが私がどこにも言及していなかったこれらのIdentityエンティティを拾い上げた理由についてまだ少し気づいていません。とにかく、何かが間違っていたのがIdentityDbContextではないことがわかったとき、エラーをスローしたコンテキストのOnModelCreatingに次を追加しました。

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Ignore <IdentityUserLogin<string>>();
            modelBuilder.Ignore <IdentityUserRole<string>>();
            modelBuilder.Ignore<IdentityUserClaim<string>>();
            modelBuilder.Ignore<IdentityUserToken<string>>();
            modelBuilder.Ignore<IdentityUser<string>>();
            modelBuilder.Ignore<ApplicationUser>();

だから...私はまだ私のコンテキストがこれらのエンティティを何の関係もなく取得している理由を疑問に思っています。コンテキストを追加するたびに、それらを含めるのではなくモデルを除外する必要があることをかなり心配しています。

4
DenLilleMand

私はあなたの最初の問題に関連する同様の問題がありました

エンティティタイプ「IdentityUserLogin」では、プライマリキーを定義する必要があります。

そして、エンティティを無視するあなたのソリューションはうまくいくように思えますが、実際に各エンティティに主キーを割り当てたい人に別のソリューションを提供したかっただけです。問題は、エンティティを作成するときはいつでも、DbContextがそれぞれの主キーを追跡する必要があることです。したがって、エンティティを割り当てる必要があります。

以下の例を参照してください。ProjectTargetはエンティティです。各エンティティの主キーとして使用するプロパティをそれぞれ割り当てました。

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Project>().HasKey(m => m.ProjectPath);
    builder.Entity<Target>().HasKey(m => m.Guid);
    base.OnModelCreating(builder);
} 

どのエンティティをそのエンティティの主キーとして指定する必要があるかを特定して割り当てた後、エラーはなくなります。

4
susieloo_