将SimpleMembership与实体框架集成

时间:2013-03-20 15:27:57

标签: entity-framework asp.net-mvc-4 simplemembership

我正在尝试将SimpleMembership表与我的对象模型的其余部分集成 - 以管理来自单个数据库和上下文的所有实体。

到目前为止,我找到了手动旋转SM表的最佳配方(将SimpleMember与我的对象模型的其余部分结合起来的入口点)here.但是,如评论部分所述提供的代码示例中有几个错误。评论试图提供更正,但由于格式化,很难遵循。

我80%的方式在那里,但却陷入了Membership表的外键生成。 OnModelCreating块中的代码是否属于MyDbContext类?我在.WithMany(u => u.Members)行上遇到编译错误。

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

编辑:下面的块包含在文章的一条评论中,但似乎不需要。

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

}

}

3 个答案:

答案 0 :(得分: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”属性。由于用户首先在Membership表中创建,因此我的UserProfile表是从属表。

<强> Membership.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; }
}

Per Richard在文章中的评论中,我注释掉了构造函数。我还创建了一个返回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课程基本保持不变;根据理查德在文章中的评论,我只注释了用户属性。

<强> 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条目。

现在已经创建了所有内容,我可以使用添加迁移更新数据库命令,并使用以下代码片段,其中包含Membership,UserProfile和角色表:

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

这是一篇很长的帖子,但我希望有所帮助。

答案 1 :(得分:1)

我使用this question的答案从我数据库中现有的'webpage_'表中自动生成模型。这可确保以与SimpleMembership创建模型完全相同的方式创建模型。这导致了以下代码:

模型:

public partial class webpages_Membership
{
   public int UserId { get; set; }
   public Nullable<System.DateTime> CreateDate { get; set; }
   public string ConfirmationToken { get; set; }
   public Nullable<bool> IsConfirmed { get; set; }
   public Nullable<System.DateTime> LastPasswordFailureDate { get; set; }
   public int PasswordFailuresSinceLastSuccess { get; set; }
   public string Password { get; set; }
   public Nullable<System.DateTime> PasswordChangedDate { get; set; }
   public string PasswordSalt { get; set; }
   public string PasswordVerificationToken { get; set; }
   public Nullable<System.DateTime> PasswordVerificationTokenExpirationDate { get; set; }
}

public partial class webpages_Roles
{
   public webpages_Roles()
   {
      this.webpages_UsersInRoles = new HashSet<webpages_UsersInRoles>();
   }

   public int RoleId { get; set; }
   public string RoleName { get; set; }

   public virtual ICollection<webpages_UsersInRoles> webpages_UsersInRoles { get; set; }
}

public partial class webpages_UsersInRoles
{
   public int UserId { get; set; }
   public int RoleId { get; set; }

   public virtual webpages_Roles webpages_Roles { get; set; }
}

Fluent Mappings:

internal partial class MembershipMapping : EntityTypeConfiguration<webpages_Membership>
{
   public MembershipMapping()
   {
      this.HasKey(t => t.UserId);
      this.ToTable("webpages_Membership");
      this.Property(t => t.UserId).HasColumnName("UserId").HasDatabaseGeneratedOption(new Nullable<DatabaseGeneratedOption>(DatabaseGeneratedOption.None));
      this.Property(t => t.CreateDate).HasColumnName("CreateDate");
      this.Property(t => t.ConfirmationToken).HasColumnName("ConfirmationToken").HasMaxLength(128);
      this.Property(t => t.IsConfirmed).HasColumnName("IsConfirmed");
      this.Property(t => t.LastPasswordFailureDate).HasColumnName("LastPasswordFailureDate");
      this.Property(t => t.PasswordFailuresSinceLastSuccess).HasColumnName("PasswordFailuresSinceLastSuccess");
      this.Property(t => t.Password).HasColumnName("Password").IsRequired().HasMaxLength(128);
      this.Property(t => t.PasswordChangedDate).HasColumnName("PasswordChangedDate");
      this.Property(t => t.PasswordSalt).HasColumnName("PasswordSalt").IsRequired().HasMaxLength(128);
      this.Property(t => t.PasswordVerificationToken).HasColumnName("PasswordVerificationToken").HasMaxLength(128);
      this.Property(t => t.PasswordVerificationTokenExpirationDate).HasColumnName("PasswordVerificationTokenExpirationDate");
   }
}

internal partial class RolesMapping : EntityTypeConfiguration<webpages_Roles>
{
   public RolesMapping()
   {
      this.HasKey(t => t.RoleId);
      this.ToTable("webpages_Roles");
      this.Property(t => t.RoleId).HasColumnName("RoleId");
      this.Property(t => t.RoleName).HasColumnName("RoleName").IsRequired().HasMaxLength(256);
   }
}

internal partial class UsersInRolesMapping : EntityTypeConfiguration<webpages_UsersInRoles>
{
   public UsersInRolesMapping()
   {
      this.HasKey(t => new { t.UserId, t.RoleId });
      this.ToTable("webpages_UsersInRoles");
      this.Property(t => t.UserId).HasColumnName("UserId").HasDatabaseGeneratedOption(new Nullable<DatabaseGeneratedOption>(DatabaseGeneratedOption.None));
      this.Property(t => t.RoleId).HasColumnName("RoleId").HasDatabaseGeneratedOption(new Nullable<DatabaseGeneratedOption>(DatabaseGeneratedOption.None));
      this.HasRequired(t => t.webpages_Roles).WithMany(t => t.webpages_UsersInRoles).HasForeignKey(d => d.RoleId);
   }
}

数据库上下文:

public class MembershipContext : DbContext, IDisposable
{
   public DbSet<webpages_Membership> Membership { get; set; }
   public DbSet<webpages_Roles> Roles { get; set; }
   public DbSet<webpages_UsersInRoles> UsersInRoles { get; set; }

   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   {
      modelBuilder.Configurations.Add(new MembershipMapping());
      modelBuilder.Configurations.Add(new RolesMapping());
      modelBuilder.Configurations.Add(new UsersInRolesMapping());

      base.OnModelCreating(modelBuilder);
   }
}

请注意,我已排除了OAuthMembership表,因为我的解决方案并不需要它。但是,如果您按照我上面提供的链接中的步骤操作,您也可以轻松地包含该表格。

答案 2 :(得分:0)

从空白的MVC4 Internet模板开始我运行项目以便在新的数据库中创建SimpleMembership表 - 然后使用EF的反向工程师工具从这些表创建POCO。逐行逐步查找错误并在OP中编辑代码块。

使用该代码后,我使用了Package Manager来&#39; Add-Migration&#39; &#39; Update-Database&#39; 。初步测试证实一切正常 - 我想如果我找到暴露任何更深层次问题的边缘案例,我将不得不重新审视。