0

我为“自动生成的”webpages_Membership 表创建了一个模型,以便我可以读取 ConfirmationToken,以防用户丢失确认电子邮件以重新发送它。这是我在 AccountModels.cs 中的代码:

[Table("webpages_Membership")]
public class webpages_Membership
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public Nullable<DateTime> CreateDate { get; set; }
    public string ConfirmationToken { get; set; }
    public Nullable<bool> IsConfirmed { get; set; }
    public Nullable<DateTime> LastPasswordFailureDate { get; set; }
    public int PasswordFailuresSinceLastSuccess { get; set; }
    public string Password { get; set; }
    public Nullable<DateTime> PasswordChangedDate { get; set; }
    public string PasswordSalt { get; set; }
    public string PasswordVerificationToken { get; set; }
    public Nullable<DateTime> PasswordVerificationTokenExpirationDate { get; set; }
}

public class UsersContext : DbContext
{
    public UsersContext()
        : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<webpages_Membership> webpages_Membership { get; set; }
}

在创建此模型之前,我可以使用以下代码行在 App_Start 上插入单个用户:

if (Membership.Provider.GetUser("admin", false) == null)
        {
            ((SimpleMembershipProvider)Membership.Provider).CreateUserAndAccount("admin", "bidchuck");
        }

然而,在实现了这个模型之后,该行现在抛出了一个异常:

[SqlException (0x80131904): Cannot insert explicit value for identity column in table 'webpages_Membership' when IDENTITY_INSERT is set to OFF.]

因此,我怀疑我的模型代码从该表中读取数据的某些内容与 WebSecurity 自动生成表的方式相冲突,这就是异常的原因。谁能解释如何更改我的模型代码,以便 WebSecurity 可以以自己的方式自动创建表?

或者,为我建议其他方式来实施“重新发送确认电子邮件”

谢谢!

4

1 回答 1

0

问题在于:

[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]

您明确告诉 EF 这是一个标识列(即,它应该为您生成一个 id)。但是,UserId 来自 ASP.NET 成员,因此您的表实际上不应生成 id

注意:删除该行后,您必须进行迁移。

更新

  1. 创建一个 POCO 来为表建模:

    [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 ICollection<Role> Roles { get; set; }
    
        [ForeignKey("UserId")]
        public ICollection<OAuthMembership> OAuthMemberships { get; set; }
    }
    

    基本上只是对表中的字段进行建模。这应该涵盖所有内容,但情况可能已经改变或可能添加了不同的约束。告诉 EF 要在[Table("webpages_Membership")]哪个表中查找,因为名称或类不完全匹配。

  2. 将您的 POCO 连接到 DbContext 子类。您将希望使用与用于实际映射实体的上下文不同的上下文(用于迁移、更新数据库等的上下文)。数据库初始化策略是在 DbContext 级别设置的,因此,如果您将其添加到用于其他所有内容的同一策略中,它将尝试迁移它,最终您会遇到来自 EF 的严重错误。

    public class SimpleMembershipContext : DbContext
    {
        public SimpleMembershipContext()
            : base("name=YourConnectStringName")
        {
            // this tells EF to not worry about migrating or modifying the database
            Database.SetInitializer<SimpleMembershipContext>(null);
        }
    
        public DbSet<Membership> Memberships { get; set; }
    }
    

    将“YourConnectionStringName”替换为项目数据库(在 web.config 中)的连接字符串的名称。如果您也将会员资料存储在其他地方,这也可能是一个完全不同的数据库。

现在,有了它,您可以像任何其他实体一样在代码中使用它:

var membershipDb = new SimpleMembershipContext();
var someMember = membershipDb.Memberships.Find(userId);
于 2013-03-28T17:01:29.353 回答