如何避免EF Core中不安全的上下文操作? [英] How to avoid not-safe context operations in EF Core?

查看:231
本文介绍了如何避免EF Core中不安全的上下文操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么使用当前数据库上下文实例作为参数创建其他类的实例并使用该数据库上下文会引发此异常的原因

I'd want to know how why creating instances of other classes with current database context instances as a parameter and using that db context causes this exception to be raised

'在先前的操作完成之前,在此上下文中开始了第二次操作.不能保证任何实例成员都是线程安全的.'

'A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.'

Imma使用此示例代码来显示问题

Imma use this sample code to show the problem

public class TestController : Controller
{
    private readonly DbContext dbContext;

    public Controller(DbContext ctx)
    {
        dbContext = ctx;
    }

    public async Task<IActionResult> Test(string id)
    {
        var isValid = new otherClass(dbContext).Validate(id);

        if (!isValid)
        {
            return View("error");
        }

        var user = dbContext.Users.FirstOrDefault(x => x.Id == id);

        user.Age++;

        dbContext.SaveChanges(); // exception is being raised here. It is second .SaveChanges() here  

        return View();
    }
}


public class otherClass
{
    private readonly DbContext dbContext;

    public otherClass(DbContext ctx)
    {
        dbContext = ctx;
    }

    public bool Validate(string id)
    {
        var user = dbContext.Users.FirstOrDefault(x => x.Id == id);

        user.ValidationAttempt = DateTime.Now;

        dbContext.SaveChanges();

        return user.HasConfirmedEmail;
    }
}

推荐答案

通常,以MVC方式,您将希望在每个请求的基础上获得DbContext,但是当使用线程时,通过使用块进行更多控制可能是有益的,这是一种简单的方法设置起来将类似于

Generally in an MVC fashion youre going to want a DbContext on a per request basis but when using threading more control through using blocks can be beneficial, an easy way to set that up would be something along the lines of

public class TestController : Controller
{
    private readonly Func<DbContext> dbContext;

    public Controller(Func<DbContext> ctx)
    {
        dbContext = ctx;
    }

    public async Task<IActionResult> Test(string id)
    {
        using(var cntx = dbContext())
        {
        var isValid = new otherClass(cntx).Validate(id);

        if (!isValid)
        {
            return View("error");
        }

        var user = cntx.Users.FirstOrDefault(x => x.Id == id);

        user.Age++;

        cntx.SaveChanges();  

        return View();
    }
    }
}

从本质上讲,每个using块都会解析一个新的DbContext-并且由于每个线程随后都在处理自己的DbContext-应该不会有任何问题

that essentially resolves a new DbContext per using block - and since each thread is then handling its own DbContext - shouldnt have any issues

这篇关于如何避免EF Core中不安全的上下文操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆