【问题标题】:This error occurs irregularly "Multiple simultaneous connections or connections with different connection~"不定期出现此错误“多个同时连接或不同连接的连接~”
【发布时间】:2021-11-11 00:21:45
【问题描述】:

我正在使用 .Net Framework 4.5,但出现以下错误:

“多个同时连接或具有不同连接的连接〜”当前不支持同一事务内的多个同时连接或具有不同连接字符串的连接。 "

我很好奇的是,这个错误并不总是发生,大约 50 次?这意味着每天大约会发生一次错误。 我不知道该怎么办,因为它只发生在生产环境中,而在本地测试中从未发生过。 如果您知道确切原因,请告诉我。

最好的尊重。

简化的来源如下。

public PartialViewResult update(string id)
{
    List<Item> list;
    try
    {
        var business = new Business();
        using (var ts = new TransactionScope(TransactionScopeOption.Required))
        {
            business.Update(id);
            ts.Complete();
        }

        if (result)
        {
            list = business.GetList();
        }
        else
        {
            Response.StatusCode = 500;
            return PartialView("Error");
        }

        return PartialView("PartialContent", list);
    }
    catch (Exception ex)
    {
        Response.StatusCode = 500;
        return PartialView("Error");
    }
}

public class Business
{
    public List<Item> GetList()
    {
        var dao = new Repository();
        var list = dao.GetList().ToList();
        return list;
    }
    
    public void Update()
    {
        try
        {
            var dao = new Repository();
            var item = dao.Get(id);
            item.UpdateDate = DateTime.Now;
            dao.Update(item);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}


public class Repository
{
    private SampleContext context;

    private Repository()
    {
        if (context == null)
        {
            context = new SampleContext();
        }
    }
    
    public IQueryable<Item> GetList()
    {
        // SQL
    }
    public IQueryable<Item> Get(string id)
    {
        // SQL
    }
    public void Update(Item item)
    {
        context.Entry(item).State = EntityState.Modified;
        context.SaveChanges();
    }
}

添加。
我试图通过 Le Vu 的评论来修改存储库。

public class Repository : IDisposable
{
    private SampleContext context;

    private Repository()
    {
        if (context == null)
        {
            context = new SampleContext();
        }
    }

    public IQueryable<Item> GetList()
    {
        // SQL
    }
    public IQueryable<Item> Get(string id)
    {
        // SQL
    }
    public void Update(Item item)
    {
        context.Entry(item).State = EntityState.Modified;
        context.SaveChanges();
    }
    
    public void Dispose()
    {
        context.Dispose();
    }
}

中途commit的原因是即使更新后重新获取数据出现错误,我们也希望按原样继续更新过程。

【问题讨论】:

  • 您是否尝试在 Repository 中调用 Dispose DbContext。我认为 DbContext 持有与数据库连接相关的非托管资源。
  • 应该在什么阶段处理 DbContext?如果在每个进程中都这样做,会是“操作无法完成。DbContext已被销毁”。 * 因为是翻译成英文的,所以可能与实际的英文信息不同。
  • 你的Repository 类应该实现IDisposable 接口。该接口有Dispose() 方法。当 GC 收集未使用的对象时,将调用此方法。您应该在 Repository 的 Dispose() 中调用 DbContext 配置。另外,请注意您的 Business 实例生命周期
  • 感谢您的评论。您需要使存储库成为一次性的。我将修改后的来源放在正文中。是这样的吗?没有这个,它可能会一直保留而不会被丢弃,是不是意味着在销毁恰好延迟的时候发生了错误?
  • 是的,你知道,垃圾收集器是 CLR 的一个特性。这意味着它只关心来自 CLR 环境的资源。这些资源称为托管资源。否则,对于这种情况下的数据库连接等非托管资源,GC 不知道它的存在。无论如何,你错过了在context 上检查null

标签: c# mysql asp.net-mvc entity-framework


【解决方案1】:

根本原因是与SampleContext(DbContext)相关的非托管资源没有被释放,尤其是这里的数据库连接。

解析是SampleContext的实例需要显式处理。这意味着,我们需要在Repository 类中实现IDisposable 接口。而在Dispose 中,我们将处理SampleContext 的实例(如果存在)。

updateAction 上 Business 对象的生命周期也是一个问题。

【讨论】:

  • 感谢您的回答!这很容易理解,因为它甚至绘制了一个图形。欣赏。至于业务,我们没有非托管资源,所以我认为进行显式 GC 是不行的。对吗?
  • 可以看到,Business对Repository、SampleContext有依赖。在 .NET Framework 中,垃圾收集并不经常发生。如果您在 update 操作完成时没有在 Business 对象中处理 Repository 对象,则 DB 连接将等待 GC 清理。您了解数据库调用的范围,因此您可以控制何时应该释放数据库。你可以在update动作中添加finally块来释放资源,
  • 对不起。我明白。之前修改源码的时候,我只是在repository中实现了IDisposable,并没有真正将实例封装在“using”中。
  • 是的,这就是我希望您注意的。您可以使存储库与业务对象一起保持活动状态,或者仅在函数范围内保持活动状态。通常,我们使用 IoC Container 从外到内控制 DbContext。它使性能更好。最佳实践是我们只处理在类中创建的对象。对于传入类的对象,我们不会触及它的生命周期。
  • 你的cmets让我很好理解。谢谢你陪我这么久。我非常乐于助人,答案令人信服。非常感谢。
猜你喜欢
  • 2011-08-28
  • 1970-01-01
  • 2020-04-04
  • 2020-08-18
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多