Entity Framework 6 и Asp.Net Identity UserManager: несколько DbContext

asp.net-identity-2 asp.net-mvc-5 c# entity-framework-6

Вопрос

Это MVC 5 / EF6. Поэтому у меня есть следующие классы:

public class User : IdentityUser
{
    public User()
    {
        Levels = new List<Level>();
    }

    [Required, MaxLength(200)]
    public string FirstName { get; set; }

    [Required, MaxLength(200)]
    public string LastName { get; set; }

    public virtual ICollection<Level> Levels { get; set; }
}

а также

public class User : IdentityUser
{
    public User()
    {
        Levels = new List<Level>();
    }

    [Required, MaxLength(200)]
    public string FirstName { get; set; }

    [Required, MaxLength(200)]
    public string LastName { get; set; }

    public virtual ICollection<Level> Levels { get; set; }
}

В дополнение к обычным таблицам членства MVC5 он создает еще 2: Levels и UserLevels (с столбцами User_Id и Level_Id). Levels таблице Levels есть статические данные (например, 1 - Отлично, 2 - Хорошо и т. Д.), И это своего рода библиотека, которую я не хочу вставлять в эту таблицу.

То, что я пытаюсь сделать, - это когда пользователь регистрируется на сайте и выбирает уровень, на котором он будет идти, и извлекает его из БД, чтобы таблица UserLevels заполнена новым UserID и выбранным LevelID . Вот мой код:

public class User : IdentityUser
{
    public User()
    {
        Levels = new List<Level>();
    }

    [Required, MaxLength(200)]
    public string FirstName { get; set; }

    [Required, MaxLength(200)]
    public string LastName { get; set; }

    public virtual ICollection<Level> Levels { get; set; }
}

Он выдает исключение в этой строке: An entity object cannot be referenced by multiple instances of IEntityChangeTracker..

var result = await UserManager.CreateAsync(user, model.Password);

Я предполагаю, что это имеет какое-то отношение к ней, пытаясь вставить в таблицу уровней уровень, который уже существует там? Конечно, это может быть что-то еще ... Любые советы? Заранее спасибо!

Принятый ответ

Если вы используете UserManager так, как это «вышло из коробки», то он, вероятно, создается таким образом:

public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext())))
{
}

public AccountController(UserManager<ApplicationUser> userManager)
{
    UserManager = userManager;
}

public UserManager<ApplicationUser> UserManager { get; private set; }

Это означает , что если вы не обеспечиваете UserManager экземпляра в AccountController конструктора (и это, вероятно , в данном случае), новый MyDbContext создан для UserManager магазина.

Тем не менее, у вас есть еще один экземпляр MyDbContext , поскольку я могу сделать вывод из этой строки в вашем коде:

public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext())))
{
}

public AccountController(UserManager<ApplicationUser> userManager)
{
    UserManager = userManager;
}

public UserManager<ApplicationUser> UserManager { get; private set; }

Все это означает, что вы должны сделать свой UserManager тем же контекстом:

public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext())))
{
}

public AccountController(UserManager<ApplicationUser> userManager)
{
    UserManager = userManager;
}

public UserManager<ApplicationUser> UserManager { get; private set; }

Таким образом, сначала MyDbContext экземпляр (только) MyDbContext , а затем передается его конструктору UserManager (как IUserStore<User> ).

Кроме того, вы можете определенно хорошо использовать инъекцию зависимостей здесь и иметь экземпляр MyDbContext введенный для вас контейнером DI, и сохранить ваш текущий код практически без изменений:

public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext())))
{
}

public AccountController(UserManager<ApplicationUser> userManager)
{
    UserManager = userManager;
}

public UserManager<ApplicationUser> UserManager { get; private set; }

См. Учебное пособие (для Microsoft Unity).




Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему