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 に 1 人のユーザーを挿入できました。

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)]

これが ID 列であること (つまり、ID を生成する必要があること) を EF に明示的に伝えています。ただし、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; }
    }
    

    基本的に、テーブル内のフィールドをモデル化するだけです。これですべてがカバーされるはずですが、状況が変わったり、別の制約が追加されたりする可能性があります。[Table("webpages_Membership")]名前またはクラスが完全に一致しないため、参照するテーブルを EF に指示します。

  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 に答える