EF6を使用するVS2013 RTM、MVC 5プロジェクトで、ApplicationUser(デフォルトでは個別のアカウント認証)に基づいてコントローラーをスキャフォールディングしようとしました。 ApplicationUser
とIdentityUser
の両方がUsersテーブルにマップされます。ウィザードは編集用のコンテキストファイルを開き、ApplicationUser(ApplicationUsers)の新しいデータベースセットを追加しようとしますが、次のエラーで失敗します。
Unable to retrieve metadata for ApplicationUser. Multiple object sets per type are not supported. The object sets ApplicationUsers and Users can both contain instances of type ApplicationUser
ソリューションには、ApplicationUsers
への参照またはインスタンスがありません。
これは既知の問題ですか?オプション付きのコマンドライン(PMCから)を使用してスキャフォールディングを実行できますか?注:ApplicationUserを参照するモデルを指定すると、scaffoldingによってコンテキストクラスに追加のデータベースセットも追加されます(アプリは、それを削除して生成コントローラーで参照を修正すると機能します)。
ワオ。誰も実際にこれの根源に到達しておらず、代わりに回避策を推奨しているだけであることに本当に驚いています。
IdentityDbContext
にはすでにプロパティが含まれています:
`public virtual IDbSet<TUser> Users { get; set; }
IdentityDbContext
をサブクラス化して独自のアプリケーション固有のコンテキストを作成する場合、どのクラスがTUser
ジェネリックを満たすかを指定する必要があります。デフォルトは次のとおりです。
public ApplicationDbContext : IdentityDbContext<ApplicationUser>
これは、次の形式の継承を介して、機能的にすでにプロパティを持っていることを意味します。
public IDbSet<ApplicationUser> Users { get; set; }
次に、次のような別のプロパティをアプリケーション固有のコンテキストに追加する場合。
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
これで、同じエンティティが2つのDbSet
sによって追跡され、そのエラーが発生します。ソリューション? DbSet
に独自のApplicationUser
を追加しないでください。名前を変更したり、上書きしたりする必要はありません。
短いバージョン:ApplicationUserクラスの名前をUserに変更します。
私はこの問題に約1か月間遭遇しましたが、まったく運がありませんでした...今まで!
最初はプレビューの問題だと思っていましたが、最新のライブラリと一緒にRTMに固執した後、この問題が移行にも持続したため、非常にイライラしました。
ただし、エラーメッセージによると、IdentityDbContextはApplicationUsersとUsersの2つのDbSetを作成しているようです。ソースコードを見るときにのみユーザーが必要です。
public class IdentityDbContext<TUser> : DbContext where TUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser
{
...
public virtual IDbSet<TUser> Users { get; set; }
...
}
このことから、私たち(およびスキャフォールディングエンジン、および移行エンジン)には、「ApplicationUsers」ではなく「Users」のみが表示されます。
この状況を修正するには、このかなり奇妙なエラーを考慮してアプリケーションクラスを調整する必要があります。 ApplicationUserクラスの名前をUserに変更するだけです:
using Microsoft.AspNet.Identity.EntityFramework
...
public class ApplicationUser : IdentityUser
{
Your Stuff
}
に:
using Microsoft.AspNet.Identity.EntityFramework
...
public class User: IdentityUser
{
Your Stuff
}
もう一度足場を試みます。クラスの行に沿って別のエラーが見つからない場合は、プロジェクトを保存し、VS2013を閉じ、VS2013を再度開き、プロジェクトをロードし、プロジェクトを再構築して、最後にスキャフォールディングを試みます。 IdentityDBContextは、ダミーの「ApplicationUsers」DBSetオブジェクトを作成して、エンティティの移行とスキャフォールディングの両方でこれらのエラーを発行することはなくなりました。
お役に立てれば!
P.S.行われたマッピングはこの問題に影響を与えないはずなので、必要に応じて同じテーブルにマッピングできるはずです。
編集:さらに問題が発生した場合は、名前の変更を元に戻してください。いくつかの問題(より多くのスキャフォールディングとクエリエラー)が発生し、ApplicationUser
に戻った後、それらの問題は消え、上記の問題は再発しませんでした。ただ頭を上げてください。
上記の問題と解決策をお読みください。私のエラーテキストは次のとおりです。
タイプごとの複数のオブジェクトセットはサポートされていません。オブジェクトセット「ApplicationUsers」と「Users」の両方に、「DataLayerIdentity.Models.ApplicationUser」タイプのインスタンスを含めることができます。
新しいコントローラーでモデル:ApplicationUserを試してみて、足場を組んだときにエラーが発生したと思われます。
以下を以下から削除することで解決しました:ApplicationDbContext.cs
public System.Data.Entity.DbSet<DataLayerIdentity.Models.ApplicationUser> ApplicationUsers
{
get;
set;
}
問題を解決するために行われたその他の変更はありません。これが誰かに役立つことを願っています。
スキャフォールディングを使用してコントロールを生成すると、vsはdbコンテキストに1行を自動的に挿入します
public System.Data.Entity.DbSet<...API.Models.ApplicationUser> ApplicationUsers { get; set; }
その行をコントローラーで削除するだけです。変化する db.ApplicationUsers
からdb.Users
この問題の解決に1日以上費やしました...:(((クラスの名前変更は回避策にすぎません。正しい解決策は、この行をApplicationContext(IdentityModels.cs)から削除することです。コードにいつ挿入されたかわかりません。
System.Data.Entity.DbSet ApplicationUsers {get;セットする; }
ユーザーは内部のどこかで管理されているため、ここにのみユーザー定義テーブルが必要です。これは、この間違った行が2回目の出現であることを意味し、これが「複数のオブジェクトセット」エラーメッセージの理由です。
この行を削除してコンパイルした後、すでに間違った宣言を参照しているため、自動生成されたビューコードにいくつかのエラーメッセージが表示されました。ビューを再作成するか、コードを手動で修正できます。ApplicationUserへの間違った参照の名前を変更して、ユーザーを修正するだけです(IdentityModels.csではなく内部のどこかで正しく定義されています)。
解決策を見つけようとしたときに、移行も破損したため、データ構造のDBへの移行を最初から開始する必要がありました。
今、私はこの問題から完全に回復し、ほぼROOTの問題は明らかです。残念ながら、根本的な問題はおそらくVS2013のバグであり、間違った追加行が作成されます。
とにかく、笑顔を続けてください。このようなバグに直面することは、Java :)でのプログラミングと比較して何もありません。
ApplicationUsersControllerを作成しようとしている場合は、次の手順に従ってください。
IdentityModels.csからこの行を削除します
public System.Data.Entity.DbSet<Project.Models.ApplicationUser> ApplicationUsers { get; set; }
プロジェクトをビルドする
control + shift + b
コントローラを生成する
Right click on the 'Controllers' folder.
Add > Controller
MVC Controller with views, using Entity Framework
Model Class: ApplicationUser
Add
IdentityModels.csに戻り、この行をもう一度削除します
public System.Data.Entity.DbSet<Project.Models.ApplicationUser> ApplicationUsers { get; set; }
プロジェクトをビルドする
control + shift + b
ApplicationUsersController.csでデータベース呼び出しをApplicationUsersからUsersに変更します
control + f to bring up 'Find and Replace'
Click 'Replace in files'
Find what: db.ApplicationUsers
Replace with: db.Users
Replace All
再生を押して指を交差させます:)
これが最も簡単な解決策です。モデルとしてApplicationUserに基づいてビュー(リスト)を追加/スキャフォールドすると、VS2013はIdentityModels.vbまたは.csファイルに次のように追加します。
System.Data.Entity.DbSet(Of ApplicationUser)としてのパブリックプロパティApplicationUsers
このプロパティを削除するだけで、問題は解決します。
また、できること:空のコントローラーを作成し、DataContextのコードを自分で追加します
protected ApplicationDbContext db { get; private set; }
public HomeController() : this(new ApplicationDbContext())
{
}
public HomeController(ApplicationDbContext db)
{
this.db = db;
}
次に、Index、Createなどのメソッドを作成し、それぞれを右クリックして[ビューの追加...]でビューを作成します。ビューをリストで足場にし、適切なテンプレートを作成し、モデルとしてApplicationUserを選択します。
重要:「データコンテキストクラス」のエントリを削除しないと、同様のエラーが再度発生します。ただし、「データコンテキストクラス」を空のままにすると、ビューのスキャフォールディングは正常に機能します。
コンテキストからDbSetを削除し、コントローラーの参照をApplicationUsersからUsersに変更することで、問題を修正しました。それは機能しましたが、今ではユーザーの足場に意味がありません。多くのことはトップレベルで維持する必要があり、それは正しく機能しません。これで、ビューモデルとリポジトリが私が行きたい方法であることがわかりました。