entity framework6和Asp.Net Identity UserManager:多个DbContext
这是MVC 5 / EF6。 所以我有以下课程:
public class User : IdentityUser { public User() { Levels = new List(); } [Required, MaxLength(200)] public string FirstName { get; set; } [Required, MaxLength(200)] public string LastName { get; set; } public virtual ICollection Levels { get; set; } }
和
public class Level { public int Id { get; set; } [Required] public string Name { get; set; } public virtual ICollection Users { get; set; } }
除了常规的MVC5成员资格表之外,它还创建了2个: Levels
和UserLevels
(带有User_Id和Level_Id列)。 Levels
表有一个静态数据(即1 – Excellent,2 – Good等)并且是一种库,我不想在这个表中插入。
我正在尝试做的是当用户在网站上注册并选择它将继续并从数据库中检索它的级别,以便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);
它在此行引发exception: An entity object cannot be referenced by multiple instances of IEntityChangeTracker..
var result = await UserManager.CreateAsync(user, model.Password);
我猜它与它试图在Levels表中插入已经存在的级别有关吗? 当然它可能是别的……有什么建议吗? 提前致谢!
如果您以“开箱即用”的方式使用UserManager
,那么它可能会像这样实例化:
public AccountController() : this(new UserManager(new UserStore (new MyDbContext()))) { } public AccountController(UserManager userManager) { UserManager = userManager; } public UserManager UserManager { get; private set; }
这意味着如果您没有向AccountController
构造函数提供UserManager
实例(这可能就是这种情况), MyDbContext
为UserManager
存储创建一个新的MyDbContext
。
然而,你有另一个MyDbContext
实例,因为我可以在你的代码中从这一行推断:
Level level = DBContext.Levels.Where(s => s.Name == model.Level.Name).SingleOrDefault();
这意味着你必须让你的UserManager
使用相同的上下文:
public AccountController() : this(null) { } public AccountController(UserManager userManager = null) { DBContext = new MyDBContext(); if (userManager == null) userManager = new UserManager (new UserStore (DBContext)); UserManager = userManager; } public UserManager UserManager { get; private set; } public MyDBContext DBContext;
这样,您首先创建(仅) MyDbContext
实例,然后将其传递给UserManager
构造函数(作为IUserStore
)。
此外,您绝对可以在这里充分利用dependency injection,并通过DI容器为您注入MyDbContext
实例,并保持当前代码几乎不变:
public AccountController(MyDBContext context) : this(new UserManager(new UserStore (context))) { this.DBContext = context; }
请参阅教程 (适用于Microsoft Unity)。