C# 如何推迟在Web窗体的不同方法中操作的多个上下文的context.save更改?

C# 如何推迟在Web窗体的不同方法中操作的多个上下文的context.save更改?,c#,asp.net,entity-framework,webforms,dbcontext,C#,Asp.net,Entity Framework,Webforms,Dbcontext,我想做的是处理单独的上下文(在单独的方法中声明),并在一个专用的方法中推迟每个上下文的SaveChanges(),因为它们在数据库的相关实体上交互 这里的问题是,我正在制作一个网络表单:这是回发区。因此,为页面声明单个上下文将触发多个上下文错误,因为每次回发后将创建一个新上下文。如果我dispose上下文以避免回发问题,我将丢失当前事务中的所有数据(不是我想要的) 如果我使用了实用程序类怎么办?这样可以创建一个静态上下文。有人告诉我这不是个好主意 我试过序列化。我的xmlserializer不想

我想做的是处理单独的上下文(在单独的方法中声明),并在一个专用的方法中推迟每个上下文的
SaveChanges()
,因为它们在数据库的相关实体上交互

这里的问题是,我正在制作一个网络表单:这是回发区。因此,为页面声明单个上下文将触发多个上下文错误,因为每次回发后将创建一个新上下文。如果我
dispose
上下文以避免回发问题,我将丢失当前事务中的所有数据(不是我想要的)

如果我使用了
实用程序
类怎么办?这样可以创建一个静态上下文。有人告诉我这不是个好主意

我试过序列化。我的
xmlserializer
不想序列化我的DbSet对象或实体类类型。我不想将数据保存在列表中以避免内存问题,因为有很多数据正在被处理

下面是我的网络表单的代码结构

怎么


您正在寻找的解决方案涉及两个更改:

  • 为上下文管理器声明一个独立类

    public class DbContextManager<C> : IDisposable where C : DbContext
    
    每次调用ContextManager.GetManager()时,它都应该检查内部关联的上下文(类型为C的私有属性:
    private C\u context;
    )是否打开。如果没有,它只会创建一个新的上下文,并在内部保存它的引用(指向C类型的私有静态属性)。或者也可以将其保存为系统用于存储广泛系统变量的某些全局属性上下文中的引用

    它还向内部整数计数器添加1,指示此ContextManager处理的引用数

    所有CRUD操作都应该在声明的
    中使用(var ctx=ContextManager.GetManager())

    当代码退出
    using
    块时,
    ContextManager
    执行它的
    Dispose()
    方法(因为类应该实现
    IDisposable
    )。在\
    Dispose()
    方法中,应该对内部整数计数器进行解列。当内部计数器达到0时,应该释放已打开的DbContext,因为不需要额外的上下文操作

    这将使您在使用系统的每个会话中只共享/保持一个到数据库的打开连接

    在多线程环境中更新静态属性/字段之前,请记住使用
    lock(\u lock)
    (object\u lock)

  • 使用本机.Net事务:为了推迟实际的
    SaveChanges()
    执行,在打开上下文之前,请使用
    TransactionScope(…)
    块:

    using (TransactionScope tr = new TransactionScope())
    
  • 使用(TransactionScope…)退出
    后,所有
    SaveChanges()
    将实际保留到数据库中。如果在执行CRUD操作时出现问题,
    TransactionScope
    将负责为您回滚所有内容

    如果使用(TransactionScope tr=new TransactionScope())嵌套
    ,或者打开多个DbContext连接,.Net事务管理器将自动升级到
    企业服务
    ,并将在open DbContext连接指向的所有Windows服务器上自动使用
    Windows分布式事务协调器服务
    。在这种情况下,您还应该在所有参与的Sql Server上配置所有DTC,以便服务器可以相互[查看和交谈],以完成此复杂场景



    如果您需要一个有效的
    DbContextManager
    类,请告诉我,我将附上一个作为示例。

    为什么要在第3个方法中保存而不是在声明上下文的位置保存?为什么需要多个上下文?@mason嘿,我想这次我的代码片段符合MVCE。。。。我需要这样做,因为这里的每个方法都是CRUD的事件(添加、修改、删除…)。因此,在同一个会话中,如果我坚持我的CRUD操作,不仅对性能不明智,而且可能导致其他错误,即我可以使用EF
    SaveChanges
    执行
    rollback
    。。。这就是我这里的问题,如果您讨论的是现有代码的问题,那么需要一个MCVE。如果你问的是如何构造代码,那就不同了。我刚刚介绍了我的应用程序(还记得昨天我们谈了很多关于XML的问题)。。。老师对我的工作很满意。对于XML问题,它已经修复了自己,我不知道如何修复…对于当前问题,我改变了方法并使用了序列化对象
        public static DbContextManager<C> GetManager()
    
        using (var ctx = ContextManager<YourContext>.GetManager())
    
        public partial class YourContext : DbContext
    
    using (TransactionScope tr = new TransactionScope())