0

这个问题有很多线程,但大多数似乎是在有人试图循环并保存在 IQueryable 而不是 IList 的上下文中出现的,这不是我正在做的。

我在控制器和存储库之间传递上下文时遇到问题。我在我的应用程序的其他地方遇到了这个问题,但下面是说明和重新创建此问题的简单方法。

首先,我在 Startup.cs 中将我的 DbContext 设置为服务。

services.AddDbContext<ApplicationDbContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

然后,我有一个控制器,它被注入。当我直接从控制器使用上下文时,前两个保存工作正常,但是当我从 repo 中使用它时,它会出错并出现标题中的异常。请注意,如果我在尝试将记录保存在我的存储库中之前将它保存在控制器中,它只会出错。

 private ApplicationDbContext _context;
 private UserManager<ApplicationUser> _userManager;

 private ApplicationUser _user
    {
        get
        {
            return _userManager.GetUserAsync(User).Result;
        }
    }

 public InitiativesController(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
    {
        _context = context;
        _userManager = userManager;
    }

    // GET: Initiatives
    public IActionResult Index()
    {

        Initiative i2 = new Initiative();
        i2.Id = 2;
        i2.InitiativeName = "testname";
        _context.Update(i2);
        _context.SaveChanges(); // Works fine

        var i4 = _context.Initiatives.SingleOrDefault(init => init.Id == 2);
        i4.InitiativeName = "blep";
        _context.Update(i4);
        _context.SaveChanges(); // Works fine


        InitiativeRepository initiativeRepository = new InitiativeRepository(_context, _user);

        var i= initiativeRepository.Get(2);
        i.InitiativeName = "blah";
        initiativeRepository.Update(i); //Throws exception

        var initiatives = initiativeRepository.GetAll();
        return View(initiatives);
    }

这是存储库类:

public class InitiativeRepository
{
    private ApplicationDbContext _context;
    private ApplicationUser _user;

    public InitiativeRepository(ApplicationDbContext context, ApplicationUser user)
    {
        _context = context;
        _user = user;
    }

    public Initiative Get(int id, bool eagerLoad = false)
    {
        if (!eagerLoad)
        {
            return _context.Initiatives.SingleOrDefault(i => i.Id == id);
        }
        else
        {
            return _context.Initiatives.Include(i => i.Tasks).ThenInclude(t => t.ActionItems).
                SingleOrDefault(i => i.Id == id);
        }
    }

    public List<Initiative> GetAll()
    {
        return _context.Initiatives.ToList();
    }

    public Initiative Update(Initiative Entity)
    {
        _context.Update(Entity);
        _context.SaveChanges(); // This line causes the exception.
        return Entity;
    }

}

这应该是任何 DB 写入的入口点,但是,我正在使用 ASP.NET 身份并自动登录此会话,所以我不确定它是否也会影响这一点。

4

1 回答 1

0

我不相信依赖注入总是会发生这样的事情。虽然这很烦人,但您可能会得到更好的服务,要么在你的 repo 中做所有事情,要么通过以下方式关闭和处理你的上下文:

using(var context = new context("yourContext"))
{
   //dowork
   context.SaveChanges();  
}

尽管不应该发生,但可能会发生什么,这只是一个猜测。是不是注入在传入时捕获了错误的上下文状态。您可以在存储库的构造函数中进行依赖注入,然后直接在存储库中使用 CRUD 操作执行所有操作。

private InitiativeRepository _initiativeRepository;


public InitiativesController(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
{
    _context = context;
    _userManager = userManager;
    _initiativeRepository = new InitiativeRepository(_context, _user);

}

我目前使用带有控制器的 .NET Core 2 Web Api 执行上述模式。我知道任何时候我保留了一个上下文并且没有关闭它,然后将该上下文与另一个使用它的状态混合在一起,我就会遇到麻烦。我也有过不为上下文使用依赖注入的想法,因此他们将其设为默认值的新 .NET Core 内容很有趣。在大型数据库和多用户应用程序完成大量工作之前,它可能会很好用。

于 2017-12-06T21:48:26.847 回答