【问题标题】:Integrating SimpleMembership with Entity Framework将 SimpleMembership 与实体框架集成
【发布时间】:2013-03-20 15:27:57
【问题描述】:

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

到目前为止,我发现手动启动 SM 表的最佳方法(将 SimpleMember 与我的对象模型的其余部分结合起来的入口点)是 here. 但是,正如 cmets 部分中所引用的,有提供的代码示例中有几个错误。 cmets 试图提供更正,但由于格式化,很难理解。

我已经完成了 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

公共 MyDbContext() :基地(“默认连接”) { }

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

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

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

}

}

【问题讨论】:

  • 你从SimpleMembership模型中改变了很多东西,这是故意的吗?比如Roles and UserProfile之间的关系我理解应该是通过Membership来实现的
  • 我非常依赖来自链接文章中包含的 cmets 的代码 - 我添加了现已删除的 FK。当我将这些模型的结果与新项目生成的数据库图进行比较时,事情就匹配上了。你看到了什么不同的东西吗?非常感谢
  • 对于那篇文章,我会先使用代码,如果你比较你生成的 POCO 和那篇文章中的内容,你会发现它们不同。先做 POCO 类,然后使用 Migration 更新您的数据库。
  • 注释的代码块是需要的,而不是您使用的。将角色映射到非 UserProfile 的成员

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


【解决方案1】:

我按照文章中的说明进行操作,同时我也考虑到了一些提示文章错误的 cmets。

我最终学习了以下课程:

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

根据文章中 Richard 的 cmets,我注释掉了构造函数。我还创建了对 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-MigrationUpdate-Database 命令并使用以下代码 sn-p 组合了 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();
}

这篇文章很长,但我希望能有所帮助。

【讨论】:

  • 好帖子但是... IAuthProvider 的具体实现在哪里?
【解决方案2】:

我使用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 映射:

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 表,因为我的解决方案不需要它。但是,如果您按照我在上面提供的链接中的步骤操作,您也可以轻松地包含该表。

【讨论】:

    【解决方案3】:

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

    有了该代码,我使用包管理器来'Add-Migration''Update-Database'。初步测试确认一切正常 - 我想如果我发现暴露任何更深层次问题的边缘情况,我将不得不重新审视。

    【讨论】:

    • 对于那篇文章,我会先使用代码,如果您比较生成的 POCO 和那篇文章中的内容,您会发现它们有所不同。先做 POCO 类,然后使用 Migration 更新您的数据库。
    • 我在实时项目中使用代码优先我只对一个临时项目使用逆向工程师来查看框架是如何连接的。
    猜你喜欢
    • 1970-01-01
    • 2023-01-28
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多