3

SimpleMembership テーブルをオブジェクト モデルの残りの部分と統合して、単一のデータベースとコンテキストからすべてのエンティティを管理しようとしています。

SM テーブル (SimpleMember をオブジェクト モデルの残りの部分と結合するためのエントリ ポイント) を手動でスピンアップするために私が見つけた最良のレシピは、ここにあります。ただし、コメント セクションで引用されているように、提供されているコード サンプルにはいくつかの間違いがあります。コメントは修正を提供しようとしますが、フォーマットされているため、フォローするのが非常に困難です。

80% は進んでいますが、Membership テーブルの外部キーの生成に行き詰まっています。OnModelCreating ブロック内のコードは MyDbContext クラスに属していますか? .WithMany(u => u.Members) 行でコンパイル エラーが発生します。

メンバーシップ.cs

[Table("webpages_Membership")]
public class Membership
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int UserId { get; set; }
    public DateTime? CreateDate { get; set; }

    [StringLength(128)]
    public string ConfirmationToken { get; set; }
    public bool? IsConfirmed { get; set; }
    public DateTime? LastPasswordFailureDate { get; set; }
    public int PasswordFailuresSinceLastSuccess { get; set; }

    [Required, StringLength(128)]
    public string Password { get; set; }
    public DateTime? PasswordChangedDate { get; set; }

    [Required, StringLength(128)]
    public string PasswordSalt { get; set; }

    [StringLength(128)]
    public string PasswordVerificationToken { get; set; }
    public DateTime? PasswordVerificationTokenExpirationDate { get; set; }

    <strike>public virtual ICollection<Role> Roles { get; set; }</strike>

編集: もともと、上記の行を追加して、以下の無関係なコード ブロックのコンパイラの苦情を削除しました。ロールへの FK を作成するこの試行を削除すると、これらのモデル クラスが SM のテーブルを生成する移行を作成するように、このコードの残りの部分が調整されます。

OAuthMembership.cs

[Table("webpages_OAuthMembership")]
public class OAuthMembership
{
    [Key, Column(Order = 0), StringLength(30)]
    public string Provider { get; set; }
    [Key, Column(Order = 1), StringLength(100)]
    public string ProviderUserId { get; set; }
    public int UserId { get; set; }
}

Role.cs

[Table("webpages_Roles")]
public class Role
{
    [Key]
    public int RoleId { get; set; }
    [StringLength(256)]
    public string RoleName { get; set; }

    public virtual ICollection<UserProfile> UserProfiles { get; set; }
}

UserProfile.cs

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }

    public virtual ICollection<Role> Roles { get; set; }
}

MyDbContext.cs

public MyDbContext() : base("DefaultConnection") { }

public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Membership> Membership { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<OAuthMembership> OAuthMembership { get; set; }


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserProfile>()
                .HasMany<Role>(r => r.Roles)
                .WithMany(u => u.UserProfiles)
                .Map(m =>
                         {
                             m.ToTable("webpages_UsersInRoles");
                             m.MapLeftKey("UserId");
                             m.MapRightKey("RoleId");
                         });

編集: 以下のブロックは記事のコメントの 1 つに含まれていましたが、必要ではないようです。

    //modelBuilder.Entity<Membership>()
    //    .HasMany<Role>(r => r.Roles)
    //    .WithMany(u => u.Members)
    //    .Map(m =>
    //    {
    //        m.ToTable("webpages_UsersInRoles");
    //        m.MapLeftKey("UserId");
    //        m.MapRightKey("RoleId");
    //    });

}

}

4

3 に答える 3

3

私は記事の指示に従いました。また、記事がいくつかの点で間違っていることを示唆するコメントも考慮しました。

私は次のクラスになりました:

UserProfile.cs

[Table("UserProfile")]
public class UserProfile
{
    [Key, ForeignKey("Membership")]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public ICollection<WebSecurity.Role> Roles { get; set; }
    public WebSecurity.Membership Membership { get; set; }
}

UserId 列で使用している "ForeignKey" 属性にすぐに気付くはずです。ユーザーは最初にメンバーシップ テーブルに作成されるため、私の UserProfile テーブルは依存テーブルです。

メンバーシップ.cs

[Table("webpages_Membership")]
public class Membership
{
    //public Membership()
    //{
    //  Roles = new List<Role>();
    //  OAuthMemberships = new List<OAuthMembership>();
    //}

    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int UserId { get; set; }
    public DateTime? CreateDate { get; set; }
    [StringLength(128)]
    public string ConfirmationToken { get; set; }
    public bool? IsConfirmed { get; set; }
    public DateTime? LastPasswordFailureDate { get; set; }
    public int PasswordFailuresSinceLastSuccess { get; set; }
    [Required, StringLength(128)]
    public string Password { get; set; }
    public DateTime? PasswordChangedDate { get; set; }
    [Required, StringLength(128)]
    public string PasswordSalt { get; set; }
    [StringLength(128)]
    public string PasswordVerificationToken { get; set; }
    public DateTime? PasswordVerificationTokenExpirationDate { get; set; }


    public UserProfile UserProfile { get; set; }
}

記事のリチャードのコメントに従って、コンストラクターをコメントアウトしました。UserProfile への参照も作成しましたが、ロールへの参照は作成しませんでした。

OAuthMembership.cs

[Table("webpages_OAuthMembership")]
public class OAuthMembership
{
    [Key, Column(Order = 0), StringLength(30)]
    public string Provider { get; set; }

    [Key, Column(Order = 1), StringLength(100)]
    public string ProviderUserId { get; set; }

    public int UserId { get; set; }

    //[Column("UserId"), InverseProperty("OAuthMemberships")]
    //public Membership User { get; set; }
}

私の OAuthMembership クラスは基本的に同じままでした。記事の Richard のコメントに従って、User 属性だけをコメントアウトしました。

AccountModel.cs+UsersContext

最後に、UserContext クラスで、UsersInRoles テーブルの関連付けを作成します。

public class UsersContext : DbContext

{

    public UsersContext()
        : base("DefaultConnection")
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<InternetApplication.Models.WebSecurity.Role>()
            .HasMany<InternetApplication.Models.UserProfile>(r => r.UserProfiles)
            .WithMany(u => u.Roles)
            .Map(m =>
            {
                m.ToTable("webpages_UsersInRoles");
                m.MapLeftKey("UserId");
                m.MapRightKey("RoleId");
            });
    }

    public DbSet<WebSecurity.Membership> Membership { get; set; }
    public DbSet<WebSecurity.OAuthMembership> OAuthMembership { get; set; }
    public DbSet<WebSecurity.Role> Roles { get; set; }
    public DbSet<UserProfile> UserProfiles { get; set; }
}

UsersInRoles マッピングを追加するだけでなく、各テーブルに DbSet エントリを追加しました。

すべてが作成されたので、Add-MigrationコマンドとUpdate-Databaseコマンドを使用して、Membership、UserProfile、および Roles テーブルを結合する次のコード スニペットを使用できます。

using (var db = new UsersContext())
{
    var memberships = db.Membership
        .Include("UserProfile")
        .Include("UserProfile.Roles")
        .ToList();
    foreach (var member in memberships)
    {
        member.IsConfirmed = true;
    }

    db.SaveChanges();
}

これは長い投稿でしたが、役に立てば幸いです。

于 2013-04-05T14:46:05.910 に答える
0

空のMVC4インターネットテンプレートから始めて、新しいデータベースにSimpleMembershipテーブルを作成するようにプロジェクトを実行しました。次に、EFのリバースエンジニアリングツールを使用して、これらのテーブルからPOCOを作成しました。エラーを見つけるために1行ずつステップスルーし、OPのコードブロックを編集しました。

そのコードを配置した状態で、パッケージマネージャーを使用して「Add-Migration」「Update-Database」を作成しました。最初のテストですべてが機能することを確認します。より深刻な問題を明らかにするエッジケースを見つけた場合は、再検討する必要があると思います。

于 2013-03-20T19:46:14.213 に答える