簡體   English   中英

實體框架6和Asp.Net Identity UserManager:多個DbContext

[英]Entity Framework 6 and Asp.Net Identity UserManager: Multiple DbContext

這是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個: LevelsUserLevels (使用User_Id和Level_Id列)。 Levels表有一個靜態數據(即1 - Excellent,2 - Good等)並且是一種庫,我不想在這個表中插入。

我正在嘗試做的是當用戶在網站上注冊並選擇它將繼續並從DB檢索它的級別,以便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);

我猜它與它試圖在Levels表中插入已經存在的級別有關嗎? 當然它可能是別的......有什么建議嗎? 提前致謝!

如果您以“開箱即用”的方式使用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; }

這意味着如果您沒有向AccountController構造函數提供UserManager實例(這可能就是這種情況), MyDbContextUserManager存儲創建一個新的MyDbContext

然而,你有另一個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實例,然后將其傳遞給UserManager構造函數(作為IUserStore<User> )。

此外,您絕對可以在此處充分利用依賴注入,並通過DI容器為您注入MyDbContext實例,並保持當前代碼幾乎不變:

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

請參閱教程 (適用於Microsoft Unity)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM