EntityFramework中多个dbcontext中的每个请求的事务

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EntityFramework中多个dbcontext中的每个请求的事务相关的知识,希望对你有一定的参考价值。

我正在使用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)

使用现有连接构造新的上下文实例以连接到数据库。如果contextOwnsConnection为false,则在处理上下文时不会处理连接。

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

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

以下是您班级所需变更的草稿,以便了解您的想法。

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();
    }
}

以上是关于EntityFramework中多个dbcontext中的每个请求的事务的主要内容,如果未能解决你的问题,请参考以下文章

EntityFramework 多个 Group by 查询

C# + EntityFramework:通过查询将多个组转换为嵌套 JSON

EntityFramework 6.x多个上下文迁移实现分布式事务

MVC5 Identity + EntityFramework 中的多个上下文

指定的密钥太长;实体框架 6 中的最大密钥长度为 767 字节 Mysql 错误

EntityFramework尝试创建指向同一个表的多个链接,FK Constraint错误