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