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 Level
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

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

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

Level level = DBContext.Levels.Where(s => s.Name == model.Level.Name).SingleOrDefault();

if (level == null)
    ModelState.AddModelError("", "Invalid Level.");

if (ModelState.IsValid)
{
    var user = new User() { 
        UserName = model.UserName,
        FirstName = model.FirstName,
        LastName = model.LastName
    };

    user.Levels.Add(level);

    var result = await UserManager.CreateAsync(user, model.Password);
    if (result.Succeeded)
    {
        await SignInAsync(user, isPersistent: false);
        return RedirectToAction("Index", "Home");
    }
    else
    {
        AddErrors(result);
    }
}
return View(model);

Он выдает исключение в этой строке: 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 , поскольку я могу сделать вывод из этой строки в вашем коде:

Level level = DBContext.Levels.Where(s => s.Name == model.Level.Name).SingleOrDefault();

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

public AccountController() : this(null)
{
}

public AccountController(UserManager<User> userManager = null)
{
    DBContext = new MyDBContext();

    if (userManager == null)
        userManager = new UserManager<User>(new UserStore<User>(DBContext));

    UserManager = userManager;
}

public UserManager<User> UserManager { get; private set; }
public MyDBContext DBContext;

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

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

public AccountController(MyDBContext context)
: this(new UserManager<User>(new UserStore<User>(context)))
{
    this.DBContext = context;
}

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



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