C# 实体框架:原子事务(数据库上下文)

C# 实体框架:原子事务(数据库上下文),c#,sql,.net,C#,Sql,.net,我正在处理实体框架4,因为应用程序已经构建好了,我必须在其中进行一些升级 场景: 在我的代码中实现了一个DBTransaction(在数据库中插入数据),一旦一个事务中途中止并执行回滚,那么下次当同一个事务使用正确/验证的数据执行时,仍然会通过给出前一个异常来中止该事务。这很难理解,因为我认为回滚应该从数据库上下文中删除验证消息和数据,因为它是SQL。 注意:我一直在使用静态数据库上下文 public class TestClass { static SampleDataBaseEnti

我正在处理实体框架4,因为应用程序已经构建好了,我必须在其中进行一些升级

场景: 在我的代码中实现了一个DBTransaction(在数据库中插入数据),一旦一个事务中途中止并执行回滚,那么下次当同一个事务使用正确/验证的数据执行时,仍然会通过给出前一个异常来中止该事务。这很难理解,因为我认为回滚应该从数据库上下文中删除验证消息和数据,因为它是SQL。 注意:我一直在使用静态数据库上下文

public class TestClass
{
    static SampleDataBaseEntities ctx = new SampleDataBaseEntities();

    public void SqlTransaction()
    {
        ctx.Connection.Open();
        using (DbTransaction transaction = ctx.Connection.BeginTransaction())
        {
            try
            {
                Student std = new Student();
                std.first_name = "first";
                //std.last_name = "last"; (This is responsible for generating the exception)
                AddTeacher();
                ctx.AcceptAllChanges();
                transaction.Commit();
            }
            catch (Exception e)
            {
                transaction.Rollback();
            }
            finally
            {
                ctx.Connection.Close();
            }
        }
    }

    public void SqlTransaction2()
    {
        ctx.Connection.Open();
        using (DbTransaction transaction = ctx.Connection.BeginTransaction())
        {
            try
            {
                Student std = new Student();
                std.first_name = "first";
                std.last_name = "last";
                AddTeacher();
                ctx.Students.AddObject(std);
                ctx.SaveChanges(false);
                transaction.Commit();
                ctx.AcceptAllChanges();
            }
            catch (Exception e)
            {
                transaction.Rollback();
                transaction.Dispose();
                ctx.Connection.Close();
            }
        }
    }

    public void AddTeacher()
    {
        Teacher t = new Teacher();
        t.first_name = "teacher_first";
        t.last_name = "teacher_last";
        t.school_name = "PUCIT";
        ctx.Teachers.AddObject(t);
        ctx.SaveChanges(false);
    }
}

class Program
{
    static void Main(string[] args)
    {
        TestClass test = new TestClass();
        test.SqlTransaction();
        test.SqlTransaction2();
    }
}
解决方案(我已经尝试过): 使用SaveChanges(false)。 使用SaveChanges(false)和ctx.AcceptAllChanges()

解决方法: 我得到的解决方法是重新实例化DatabaseContext对象

因为我在重新实例化上下文时遇到了复杂性问题,这就是为什么要寻找更合适的解决方案。
提前感谢。

所有问题都源于没有创建上下文的新实例。将您的代码简化到这一点,它应该可以工作

using (var ctx = new SampleDataBaseEntities()) {
    Student std = new Student();
    std.first_name = "first";
    std.last_name = "last";
    ctx.Student.Add(std);
    ctx.SaveChanges();
}

所有问题都源于不创建上下文的新实例。将您的代码简化到这一点,它应该可以工作

using (var ctx = new SampleDataBaseEntities()) {
    Student std = new Student();
    std.first_name = "first";
    std.last_name = "last";
    ctx.Student.Add(std);
    ctx.SaveChanges();
}
“我得到的解决方法是重新实例化DatabaseContext对象。”

是,这对于再次执行事务是正确的。 由于您使用的是静态数据上下文,因此下次执行事务时,将使用相同的数据上下文,这会导致您在重新输入数据和验证错误时遇到问题

解决方案:尽量不要使用静态dataContext,因为您可以更快地完成事务。因此,您需要为每个事务更新datacontext。因此,始终尝试实例化一个新的dataContext,并在事务完成后立即销毁它。 希望它能起作用

“我得到的解决方法是重新实例化DatabaseContext对象。”

是,这对于再次执行事务是正确的。 由于您使用的是静态数据上下文,因此下次执行事务时,将使用相同的数据上下文,这会导致您在重新输入数据和验证错误时遇到问题

解决方案:尽量不要使用静态dataContext,因为您可以更快地完成事务。因此,您需要为每个事务更新datacontext。因此,始终尝试实例化一个新的dataContext,并在事务完成后立即销毁它。

希望它能起作用

不要使用静态数据库上下文。根据需要创建一个。此外,不需要手动处理SQL事务。什么是“重新实例化上下文的复杂性问题”?不要使用静态DbContext,因为它不是线程安全的。另外,请始终使用
using
语句,以便在出现任何错误时,上下文将回滚任何更改。请尽可能晚地创建上下文,并尽快处理它(使用using!)。当然不是静态的。如果您有“复杂性问题”,请首先解决这些问题;然后以正确的方式使用上下文,正如前面其他人提到的。实际上,在应用程序中,上下文是在构造函数中创建的,并在整个应用程序中使用。这是使用上下文对象的正确方法吗?不要使用静态数据库上下文。根据需要创建一个。此外,不需要手动处理SQL事务。什么是“重新实例化上下文的复杂性问题”?不要使用静态DbContext,因为它不是线程安全的。另外,请始终使用
using
语句,以便在出现任何错误时,上下文将回滚任何更改。请尽可能晚地创建上下文,并尽快处理它(使用using!)。当然不是静态的。如果您有“复杂性问题”,请首先解决这些问题;然后以正确的方式使用上下文,正如前面其他人提到的。实际上,在应用程序中,上下文是在构造函数中创建的,并在整个应用程序中使用。这是使用上下文对象的正确方法吗?是的!我明白你的意思,不要创建一个静态的上下文对象。无论问题是什么,上下文对象都在构造函数中初始化,并在整个应用程序中使用。在原子事务场景中,当事务中途中止时,上下文对象保留异常。下次当我尝试使用该上下文时,它会向我显示前面的异常。为什么会这样?这是因为您再次使用了“错误的”dataContext。如果您在同一个类中需要相同的对象,那么为什么需要将其设置为静态?这将导致问题,因为如果您创建了TestClass的多个对象,那么将使用相同的脏数据上下文。因为DataContext应该有最短的生命周期。您还可以在类中实例化非静态DataContext,该类可以在整个过程中用于同一对象。我理解DataContext重新实例化的目的和优点。如果我不能自由地重新实例化,是否有任何方法可以刷新或清理DbContext?是的!我明白你的意思,不要创建一个静态的上下文对象。无论问题是什么,上下文对象都在构造函数中初始化,并在整个应用程序中使用。在原子事务场景中,当事务中途中止时,上下文对象保留异常。下次当我尝试使用该上下文时,它会向我显示前面的异常。为什么会这样?这是因为您再次使用了“错误的”dataContext。如果您在同一个类中需要相同的对象,那么为什么需要将其设置为静态?这将导致问题,因为如果您创建了TestClass的多个对象,那么将使用相同的脏数据上下文。因为DataContext应该有最短的生命周期。您还可以在类中实例化非静态DataContext,该类可以在整个过程中用于同一对象。我理解DataContext重新实例化的目的和优点。如果我不能自由地重新实例化,有吗