C# EF中事务回滚后写入日志表

C# EF中事务回滚后写入日志表,c#,.net,sql-server,entity-framework,transactions,C#,.net,Sql Server,Entity Framework,Transactions,在EF中事务回滚之后,我需要写入日志表。 当前代码: using (MyDataBase db = new DataBase()) { using (var dbContextTransaction = db.Database.BeginTransaction()) { try { //Inserting several records to different tables var newEntit

在EF中事务回滚之后,我需要写入日志表。 当前代码:

using (MyDataBase db = new DataBase())
{
    using (var dbContextTransaction = db.Database.BeginTransaction())
    {
        try
        {
            //Inserting several records to different tables
            var newEntity = new Entity();
            ...
            db.Entity.Add(newEntity);

            db.SaveChanges();
            db.up_StoredProcCall;
            dbContextTransaction.Commit();
        }
        catch (Exception ex)
        {
            dbContextTransaction.Rollback();

            var logEntry = new LogEntry();
            ...
            db.LogEntry.Add(logEntry);
            db.SaveChanges();
        }
    }
}
它不起作用,因为EF会在内部缓存所有插入,并在单个事务中刷新它们:

db.LogEntry.Add(logEntry);
db.SaveChanges();
实现目标的最佳方式是什么:

是否创建单独的DbContext以插入日志记录? 通过ChangeTracker放弃更改,如所述或?我个人认为这不是一个好主意,因为这样我就根本不需要使用事务。 任何其他选择都将不胜感激
使用失败的SaveChanges关闭DbContext,并从新的日志项写入日志项。好了,没有办法放弃DbContext中挂起的更改

乙二醇


在SQL server端,如果事务回滚,它通常不是一个修辞,这是它的技术术语,意味着不能执行更多的数据修改语句,包括对日志表的任何写入。因此,您必须至少需要一个单独的事务来记录失败。确切地说,我不熟悉EF如何处理事务。如果它对dbContextTransaction仍然存在感到不安,请将异常存储在catch中的一个局部变量中,然后检查它并在using外部记录。EF中的事务只更改SQL端更改的事务上下文。通常,它将SaveChanges调用之前所做的所有更改封装在一个阶段中。事务上下文改变了这一点,例如在事务中包含存储过程的调用。但它对ChangeTracker没有任何作用。因此,将日志表插入从事务作用域移开将不会有帮助,因为事务中所做的所有更改都将保留在EF的缓存ChangeTracker中,并将在SaveChanges上转到DB。只有将日志表插入移动到另一个DbContext中才会有所帮助。但可能还有更方便的解决方案?在SQL server端,如果事务回滚。。。这意味着没有更多的数据修改语句可以执行-这不是真的。回滚将仅放弃事务中所做的所有更改。但是在回滚之后,您可以向DB写入。你是对的,我把它和错误混淆了,这些错误在事务回滚之前就注定了它的命运。不是所有的错误都会导致事务终止,也不是所有的错误都会导致事务终止。在显式回滚之后,事务不再存在,所以忘记所有这些。谢谢David!但是,在创建新的DbContext之前,是否需要显式地处理第一个DbContext?我认为新的DbContext在创建时不应该有挂起的更改,并且对新的DbContext调用SaveChanges不应该受到第一个上下文中所做更改的影响。它将在离开catch块后由.NET处理。同时打开两个上下文是否存在任何风险或缺点?不需要。但是,如果在打开新的DbContext之前回滚事务并处理DbContext,则可能会重用相同的池连接。顺便问一下,事务的创建是否会对Entity.Add、Entity.Remove和update等方法产生影响?或者它只改变SaveChanges方法的行为?换句话说,我可以在调用SaveCahnges之前创建事务吗?如下所示:创建上下文、进行数据更改、创建事务、保存更改、调用SP、提交/回滚?您可以在第一次保存更改之前启动事务,但较早启动事务并不有害。我理解较早启动事务不会有任何伤害。这个问题只是为了让我理解它到底是做什么的。我有两个选择:它可以标记ChangeTracker中的对象,或者只是改变SaveChanges方法的行为。现在很明显,后者是正确的。谢谢!
using (MyDataBase db = new DataBase())
{
    using (var dbContextTransaction = db.Database.BeginTransaction())
    {
        try
        {
            //Inserting several records to different tables
            var newEntity = new Entity();
            ...
            db.Entity.Add(newEntity);

            db.SaveChanges();
            db.up_StoredProcCall;
            dbContextTransaction.Commit();
        }
        catch (Exception ex)
        {
            dbContextTransaction.Rollback();
            db.Dispose();

            using (MyDataBase dbLog = new DataBase())
            {
              var logEntry = new LogEntry();
              ...
              dbLog.LogEntry.Add(logEntry);
              dbLog.SaveChanges();

            }

        }
    }
}