简体   繁体   English

自定义SimpleMembership

[英]Customizing SimpleMembership

After reading this good BLOG about adding custom data to UserProfile table, I wanted to change it the way that UserProfile table should store default data + another class where all additional info is stored. 在阅读了关于向UserProfile表添加自定义数据的好BLOG之后,我想以UserProfile表应该存储默认数据的方式更改它+另一个存储所有其他信息的类。

After creating new project using Interenet application template, I have created two classes: 使用Interenet应用程序模板创建新项目后,我创建了两个类:

Student.cs Student.cs

[Table("Student")]
public class Student
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public virtual int StudentId { get; set; }
    public virtual string Name { get; set; }
    public virtual string Surname { get; set; }
    public virtual int UserId { get; set; }
}

UserProfile.cs UserProfile.cs

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

also, I've deleted the UserProfile definition from AccountModel.cs. 另外,我从AccountModel.cs中删除了UserProfile定义。 My DB context class looks like this: 我的DB上下文类看起来像这样:

MvcLoginDb.cs MvcLoginDb.cs

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

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<Student> Students { get; set; }
}

again, I have deleted db context definition from AccountModel.cs. 我再次从AccountModel.cs中删除了db上下文定义。

Inside Package-Manager-Console I've written: 在Package-Manager-Console内部我写道:

Enable-Migrations

and my Configuration.cs looks like this: 我的Configuration.cs看起来像这样:

internal sealed class Configuration : DbMigrationsConfiguration<MvcLogin.Models.MvcLoginDb>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(MvcLogin.Models.MvcLoginDb context)
    {
        WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

        if (!WebSecurity.UserExists("banana"))
            WebSecurity.CreateUserAndAccount(
                "banana",
                "password",
                new
                {
                   Student = new Student { Name = "Asdf", Surname = "Ggjk" }
                });

    }
}

That was the idea of adding student data as creating a new class, but this approach is not working because after running Update-Database -Verbose I'm getting the error: No mapping exists from object type MvcLogin.Models.Student to a known managed provider native type. 这是将学生数据添加为创建新类的想法 ,但这种方法不起作用,因为在运行Update-Database -Verbose之后我收到错误: 从对象类型MvcLogin.Models.Student到已知托管不存在映射提供者本机类型。

Can anyone expain why I'm getting this error, shoud I use a different approach for storing additional data in different table? 任何人都可以说明为什么我会收到此错误,我应该使用不同的方法在不同的表中存储其他数据?

I struggled a lot with the same issue. 我在同样的问题上苦苦挣扎。 The key is to get the relation between the UserProfile class and your Student class correct. 关键是要使UserProfile类和Student类之间的关系正确。 It have to be a one-to-one relationship in order to work correct. 它必须是一对一的关系才能正常工作。

Here is my solution: 这是我的解决方案:

Person.cs Person.cs

public class Person
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    /* and more fields here */

    public virtual UserProfile UserProfile { get; set; }
}

UserProfile.cs UserProfile.cs

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

    public virtual Person Person { get; set; }
}

MyDbContext.cs MyDbContext.cs

public class MyDbContext : DbContext
{
    public DbSet<Person> Person { get; set; }
    public DbSet<UserProfile> UserProfile { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
     modelBuilder.Entity<UserProfile>()
                    .HasRequired(u => u.Person)
                    .WithOptional(p => p.UserProfile)
                    .Map(m => m.MapKey("PersonId"));
    }
}

However, I also struggled with creating users with the WebSecurity.CreateUserAndAccount method. 但是,我也在努力使用WebSecurity.CreateUserAndAccount方法创建用户。 So I ended up creating my Person objects with Entity Framework and then create the user account with the membership provider method: 所以我最终使用Entity Framework创建了Person对象,然后使用成员资格提供程序方法创建了用户帐户:

AccountRepository.cs AccountRepository.cs

 public Person CreatePerson(string name, string username) {

     Person person = new Person { Name = name };
     _dbContext.Person.add(person);
     _dbContext.SaveChanges();

     var membership = (SimpleMembershipProvider)Membership.Provider;
     membership.CreateUserAndAccount(
         model.UserName, 
         createRandomPassword(), 
         new Dictionary<string, object>{ {"PersonId" , person.Id}}
     );

 }

HenningJ, I'm searching for an answer to the same thing. HenningJ,我正在寻找同样的答案。 Unfortunately (I'm sure you're aware) the problem with the way you did this is that there is no SQL transaction. 不幸的是(我确定你知道)你这样做的问题是没有SQL事务。 Either your SaveChanges() or CreateUserAndAccount() could fail leaving your user database in an invalid state. 您的SaveChanges()或CreateUserAndAccount()可能会失败,使您的用户数据库处于无效状态。 You need to rollback if one fails. 如果一个失败,您需要回滚。

I'm still searching for the final answer, but I'll post whatever solution I end up going with. 我仍然在寻找最终的答案,但我会发布我最终的解决方案。 Hoping to avoid having to write a custom membership provider (AGAIN!), but starting to think it would be faster. 希望避免编写自定义成员资格提供程序(AGAIN!),但开始认为它会更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM