Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不传递上下文的情况下读取添加到DbContext的实体_C#_Database_Entity Framework_Transactionscope - Fatal编程技术网

C# 如何在不传递上下文的情况下读取添加到DbContext的实体

C# 如何在不传递上下文的情况下读取添加到DbContext的实体,c#,database,entity-framework,transactionscope,C#,Database,Entity Framework,Transactionscope,我目前正在研究一个系统,其各层之间的通信非常复杂,有几个类负责查询数据库,每个类都有一个DbContext实例,这些类由一个负责向数据库提交数据的类和一个负责从数据库查询只读数据的类调用。 现在的情况是,“writer”类必须为其中的每个调用传递此上下文,比如: public class Writer { private DbContextClass _context; public DbContextClass Context { get

我目前正在研究一个系统,其各层之间的通信非常复杂,有几个类负责查询数据库,每个类都有一个DbContext实例,这些类由一个负责向数据库提交数据的类和一个负责从数据库查询只读数据的类调用。 现在的情况是,“writer”类必须为其中的每个调用传递此上下文,比如:

public class Writer {
    private DbContextClass _context;
    public DbContextClass Context
    {
        get
        {
            if (_context == null)
            {
                _context = new DbContextClass();
            }
            return _context;
        }
        set
        {
            _context = value;
        }
    }

    public void WriteToDatabase() {
        MethodCallA();
        MethodCallB();
        MethodCallC();
        Context.SaveChanges();
    }

    public void MethodCallA() {
        var entityA = (from c in Context.EntitiesA where c.id == 1).FirstOrDefault();
        entityA.FieldA = "changed";
        Context.SaveChanges();
    }

    public void MethodCallB() {
        //very long task here, probably creating a pdf and uploading to another place
        var entityB = new EntitiesB();
        entityB.FieldB = "new";
        Context.AddToEntitiesB(entityB);
    }

    public void MethodCallC() {
        var changedEntityA = (from c in Context.EntitiesA where c.id == 1).FirstOrDefault();
        var newEntityB = (from c in Context.EntitiesB where c.FieldB == "new").FirstOrDefault();
        var newEntityC = new EntitiesC();
        newEntityC.FieldC = newEntityB.FieldB + changedEntityA.FieldA;
        Context.AddToEntitiesC(newEntityC);
    }
}
因此,它们在方法上共享相同的上下文的原因是为了能够像我在MethodCallC()上所做的那样,在将实体发送到数据库之前,能够在上下文中插入实体

我想知道是否有可能重构这些方法,因此每个方法都有自己的上下文,并且仍然能够获得相同的结果,换句话说,仍然能够读取尚未发送到数据库的数据

我的第一个想法是删除“Context”属性,并在每个方法中创建一个新的上下文,唯一的问题是这些操作可能是原子的,也可能不是原子的,也就是说,有些方法只需将数据更新到数据库中,而不必担心发生了什么,因此调用SaveChanges,还有一些方法依赖于对上下文所做的更改,因此我认为这应该在“WriteToDatabase”方法中调用TransactionScope,围绕所有其他方法,其背后的原因是我希望确保每次对数据库的调用占用尽可能少的时间,从今天起,我真的不知道数据库连接何时关闭,对吗

简而言之,TransactionScope能否保证在其作用域内创建的每个新DbContext都会读取尚未提交到数据库中的数据(在调用SaveChanges之前),以便其他方法可以创建自己的上下文并尽可能快地关闭连接? 还有一个问题,由于连接在某个时刻会在事务内部打开,它会一直打开直到事务结束吗?还是在执行查询后立即关闭


我最大的挑战是确保这段代码与数据库的通信时间尽可能短。

我认为您在解决问题时使用了错误的模式。您应该了解Repository和UnitOfWork模式,并使用依赖项注入来确保在一个工作单元的所有组件中使用相同的DbContext。这是一个很好的例子


您必须了解这些模式,并根据您的应用程序进行调整。

这听起来像是一个CQRS类型设置-我想没有非规范化的读取模型等

我会看看依赖注入。它可以控制生命周期范围等。您的代码听起来很难维护-传递上下文从来都不是一个好迹象

这里讨论的是会话管理,它相当于EF上下文

您可能希望了解使用DI的命令模式和处理程序。像这样的


您可以使用Decorator模式来管理命令的事务范围。

这不是对您问题的直接回答,但请看一看,非常感谢,通过阅读您提到的模式,我相信构建系统的人可能试图创建类似的东西,我认为可以将事务和一个上下文结合起来以获得这样的结果,但是我将继续阅读这些模式,以找到移动当前架构的最佳方式