忽略TransactionScope进行特定查询 [英] Ignore TransactionScope for specific query

查看:105
本文介绍了忽略TransactionScope进行特定查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种在TransactionScope存在时执行查询的方法,并忽略TransactionScope - 基本上,我想执行这个特定的查询,无论什么。



我正在使用EF代码优先,并且应用程序的设计方式,一个新的数据上下文在单个调用中多次打开,每个调用都有自己的更改,所有这些都包含在一个TransactionScope中,其中 Complete()在结束时调用,假设没有失败。在上下文中,我们覆盖了 SaveChanges ,以便在 base.SaveChanges()中发生任何异常时,我们可以在回滚事务之前,请抓住它并登录到数据库。



由于事务中发生了 SaveChanges 记录显然不会发生,因为它属于与原始调用相同的事务。我试图忽略TransactionScope只是为了记录代码。



这里有一些删除代码:

  //从上下文
public override int SaveChanges(){
try {
return base.SaveChanges();
} catch(Exception ex){

//写入日志表 - 我希望这可以运行,无论什么
LogRepo.Log(/ *东西从上下文* /);

throw;
}
}

//内部业务逻辑
public void DoSomething(){
try {
using(var scope = new TransactionScope()){

using(var context = new FooContext()){
// do something
context.SaveChanges();
}
使用(var context = new FooContext()){
//执行其他操作
context.SaveChanges();
}

scope.Complete();
}
} catch(Exception ex){
// scope.Complete从不调用,所以事务被回滚
}
}

我尝试使用常规的ADO.NET而不是EF进行日志记录,但仍然是相同的结果 - 它也被回滚了。



我需要在 SaveChanges 之内发生错误处理,因为我正在记录的是正在保存的实体 - 所以我不能轻易地将记录移动到别的地方。我可以在 SaveChanges catch 内部构建消息,然后将其发送并让 DoSomething catch 登录,但是几十个 DoSomething 方法,我宁愿在一个地方处理这个问题。

解决方案

如果在启用了禁用选项的情况下将日志调用包裹在另一个事务范围内,则不会使用事务范围。

 code> public override int SaveChanges(){
try {
return base.SaveChanges();
} catch(Exception ex){

string message = / *从上下文记录的东西* /;
using(var scope = new TransactionScope(TransactionScopeOption.Suppress))
{
LogRepo.Log(msg);

}

throw;
}

}


I'm looking for a way to execute a query while a TransactionScope is alive, and ignore the TransactionScope - basically, I want to execute this particular query no matter what.

I'm using EF code-first, and the way the application is designed, a new data context is opened many times throughout a single call, each with its own changes, and all of those are contained within a single TransactionScope, which has Complete() called at the end assuming no failures. Inside of the context we've overridden SaveChanges so that if any exception happens on base.SaveChanges(), we can catch it and log to the database before rolling back the transaction.

Since the SaveChanges happens inside the transaction, the logging obviously doesn't happen, because it belongs to the same transaction as the original call. I'm trying to ignore the TransactionScope altogether just for the logging code.

Here's some stripped-down code:

// From the context
public override int SaveChanges() {
    try {
        return base.SaveChanges();
    } catch (Exception ex) {

        // Writes to the log table - I want this to run no matter what
        LogRepo.Log(/*stuff to log from the context*/);

        throw;
    }
}

// Inside the business logic
public void DoSomething() {
    try {
        using (var scope = new TransactionScope()) {

            using (var context = new FooContext()) {
                // Do something
                context.SaveChanges();
            }
            using (var context = new FooContext()) {
                // Do something else
                context.SaveChanges();
            }

            scope.Complete();
        }
    } catch (Exception ex) {
        // scope.Complete is never called, so the transaction is rolled back
    }
}

I tried using regular ADO.NET instead of EF for the logging, but still the same results - it gets rolled back too.

I need the error handling to happen inside of SaveChanges, because what I'm logging is the state of the entities that are being saved - so I can't just easily move the logging somewhere else. I could build the message while inside the SaveChanges catch, and throw it and let DoSomething catch log it, but there are dozens of DoSomething methods, and I'd much rather just deal with this in one place.

解决方案

If you wrap your log call inside of another transaction scope with the suppress option enabled, transaction scope will not be used.

public override int SaveChanges() {
try {
    return base.SaveChanges();
} catch (Exception ex) {

    string message = /*stuff to log from the context*/;
    using (var scope = new TransactionScope(TransactionScopeOption.Suppress))
    {
        LogRepo.Log(msg);

    }

    throw;
}

}

这篇关于忽略TransactionScope进行特定查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆