c# - EntityFramework 中多个 dbcontext 中每个请求的事务

标签 c# asp.net-mvc transactions entity-framework-6

我正在使用 Asp.Net MVC 和 Entity Framework 。我有一个类来管理每个请求的事务,如下所示:

public class TransactionPerRequest :
    IRunOnEachRequest, IRunOnError, IRunAfterEachRequest
{
    private readonly ContextDB _Context;
    private readonly HttpContextBase _HttpContext;

    public TransactionPerRequest(ContextDB context,
        HttpContextBase httpContext)
    {
        _Context = context;
        _HttpContext = httpContext;
    }

    void IRunOnEachRequest.Execute()
    {
        _HttpContext.Items["_Transaction"] =
            _Context.Database.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    void IRunOnError.Execute()
    {
        _HttpContext.Items["_Error"] = true;
    }

    void IRunAfterEachRequest.Execute()
    {
        var transaction = (DbContextTransaction)_HttpContext.Items["_Transaction"];

        if (_HttpContext.Items["_Error"] != null)
            transaction.Rollback();
        else
            transaction.Commit();
    }
}

我想使用多个上下文,如所解释的 here

如何更改 TransactionPerRequset 类?

最佳答案

我已经做到了,

关键是从 EF 中控制数据库连接生命周期,并自行处理连接初始化、打开、关闭和处置。

为此,您将使用以下基本 DbContext 构造函数:DbContext(DbConnection connection, Boolean contextOwnsConnection)

Constructs a new context instance using the existing connection to connect to a database. The connection will not be disposed when the context is disposed if contextOwnsConnection is false.

您应该在所有应用程序上下文中使用 DbConnection 公开构造函数,并注入(inject)您在 DbContext 外部创建的相同连接。这样 EF 将不会创建和打开它们。

最后,在您的连接管理器类中,您可以使用 DbConnection.BeginTransaction() 来获取 DbTransaction 对象并根据您的需要使用它。

下面是您的类(class)所需更改的草稿,以便让大家理解这个想法。

public partial class ContextDB : DbContext
{
    // New constructor
    public ContextDB(DbConnection connection)
        : base(connection, false)
    {
    }
}

public class TransactionPerRequest :
    IRunOnEachRequest, IRunOnError, IRunAfterEachRequest
{
    private readonly ContextDB _Context;
    private readonly HttpContextBase _HttpContext;
    private readonly DbConnection _cnn;

    public TransactionPerRequest(HttpContextBase httpContext)
    {
        // Your code creates the connection
        _cnn = new SqlConnection("Data Source=.;Initial Catalog=DB;Integrated Security=SSPI;");
        // Pass connection your context
        _Context = new ContextDB(_cnn);
        _HttpContext = httpContext;
    }

    void IRunOnEachRequest.Execute()
    {
        // Open connection
        _cnn.Open();
        _HttpContext.Items["_Transaction"] =
            _cnn.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    void IRunOnError.Execute()
    {
        _HttpContext.Items["_Error"] = true;
    }

    void IRunAfterEachRequest.Execute()
    {
        var transaction = (DbContextTransaction)_HttpContext.Items["_Transaction"];

        if (_HttpContext.Items["_Error"] != null)
            transaction.Rollback();
        else
            transaction.Commit();

        _cnn.Close();
        _cnn.Dispose();
    }
}

关于c# - EntityFramework 中多个 dbcontext 中每个请求的事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40951508/

相关文章:

c# - 包含在 .gitignore Visual Studio *.tlog 文件中是否安全?

javascript - 无法使用 Ajax 将数据列表从 Controller 返回到 View 中的下拉列表。我收到未定义的未定义错误

mysql - FOR UPDATE 似乎没有锁定 MySql InnoDB 中的行

MySQL:如何查找被事务锁定的行

java - 我可以将 Hibernate 与 JTA 一起使用吗?

c# - Asp.net 自动完成扩展器不工作

c# - 坚持对象创建

c# - 将标签移出饼图

c# - 弹出 - 阻止了带有来源的框架

c# - 带有 WellKnownText 空间数据列的 SqlBulkCopy DataTable