Настройка SimpleMembership

После прочтения этого хорошего -properties/" rel="nofollow">БЛОГ о добавлении пользовательских данных в таблицу UserProfile, я хотел изменить его так, чтобы таблица UserProfile хранила данные по умолчанию + другой класс, в котором хранится вся дополнительная информация.

После создания нового проекта с использованием шаблона приложения Interenet я создал два класса:

Студент.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

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

Кроме того, я удалил определение UserProfile из AccountModel.cs. Мой класс контекста БД выглядит так:

MvcLoginDb.cs

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

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

опять же, я удалил определение контекста БД из AccountModel.cs.

Внутри Package-Manager-Console я написал:

Enable-Migrations

и мой 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" }
                });

    }
}

Это была идея добавления данных учащихся при создании нового класса, но этот подход не работает, потому что после запуска Update-Database -Verbose я получаю сообщение об ошибке: < strong>Не существует сопоставления типа объекта MvcLogin.Models.Student с собственным типом известного управляемого поставщика.

Может ли кто-нибудь объяснить, почему я получаю эту ошибку, следует ли использовать другой подход для хранения дополнительных данных в другой таблице?


person Banana    schedule 02.03.2013    source источник
comment
Новая идентификация ASP.NET framework, похоже, был переписан для MVC 5. Похоже, они решили проблему с дополнительными полями в пользовательской модели: Новая база данных членства управляется Entity Framework Code First, и все таблицы представлены классами сущностей, которые вы можете изменить. Это означает, что вы можете легко настроить схему базы данных и веб-интерфейс, связанный с профилем, в соответствии со своими потребностями, а также легко развертывать обновления с помощью Code First Migrations.   -  person HenningJ    schedule 01.10.2013


Ответы (2)


Я много боролся с той же проблемой. Ключ в том, чтобы правильно установить связь между классом UserProfile и вашим классом Student. Это должно быть отношение один к одному, чтобы работать правильно.

Вот мое решение:

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

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

    public virtual Person Person { get; set; }
}

Мидбконтекст.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"));
    }
}

Однако у меня также возникли проблемы с созданием пользователей с помощью метода WebSecurity.CreateUserAndAccount. В итоге я создал свои объекты Person с помощью Entity Framework, а затем создал учетную запись пользователя с помощью метода поставщика членства:

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

 }
person HenningJ    schedule 14.03.2013
comment
Я понимаю ваше решение. Тем временем я нашел кое-что отличное в NuGet. Взгляните, я планирую использовать этот подход: codefirstmembership.codeplex.com - person Banana; 16.03.2013
comment
Похоже, это действительно интересный проект. Возможно, я попробую его в своем следующем проекте. - person HenningJ; 18.03.2013

HenningJ, я ищу ответ на то же самое. К сожалению (я уверен, вы знаете), проблема с тем, как вы это сделали, заключается в том, что нет транзакции SQL. Либо ваш SaveChanges(), либо CreateUserAndAccount() могут не работать, оставляя вашу базу данных пользователей в недопустимом состоянии. Вам нужно откатиться, если один из них не работает.

Я все еще ищу окончательный ответ, но я опубликую любое решение, которое я в конечном итоге выберу. Надеясь избежать необходимости писать собственный провайдер членства (ОПЯТЬ!), но начинаю думать, что это будет быстрее.

person jrichview    schedule 19.07.2013