1

考虑到这个类

public class XQueries
{
    public IQueryable Query1()
    {
        using (XEntities context = new XEntities())
        {
            return something;
        }
    }

    public IQueryable Query2()
    {
        using (XEntities context = new XEntities())
        {
            return somethingElse;
        }
    }
}

是否为每个 (XEntities context = new XEntities()) {...} 创建了与数据库的连接?如果是这样,创建静态 UnitOfWork 类以便只存在 1 个连接的正确方法是什么?

4

2 回答 2

1

您不能创建静态的工作单元,因为根据定义,工作单元是一个短暂的对象。因为 EF是围绕工作单元模式设计的,所以在应用程序的生命周期内ObjectContext拥有单个实例是一个坏主意。ObjectContext有几个原因。

首先,ObjectContext该类不是线程安全的。这意味着在一个用户的工作单元期间(例如在 Web 应用程序中),另一个用户可以提交他的工作单元。当它们共享相同时ObjectContext,这意味着在这种情况下,只有一半的更改是持久的,并且更改不是事务性的。当你幸运时,ObjectContext失败并引发异常。当你不走运时,你会破坏ObjectContext数据库的安全和加载垃圾,并找出你的应用程序何时在生产中运行(当然,在测试和登台期间,一切似乎总是有效的)。

其次,它ObjectContext有一个缓存机制,旨在使其寿命短。当从数据库中检索实体时,它会保留在ObjectContext的缓存中,直到该实例被垃圾回收。当您使该实例长时间保持活动状态时,实体会变得陈旧。特别是如果该特定ObjectContext实例不是唯一写入该数据库的实例。

于 2010-08-01T13:08:40.470 回答
0

实体框架仅在需要时打开连接,例如执行查询或调用 SaveChanges,然后在操作完成时关闭连接。

来自 Martin Fowler 的关于工作单元的企业应用程序架构模式一书。

当您将数据导入和导出数据库时,跟踪您所做的更改非常重要。否则,该数据将不会被写回数据库。同样,您必须插入您创建的新对象并删除您删除的任何对象。

您可以在每次更改对象模型时更改数据库,但这可能会导致大量非常小的数据库调用,最终会非常慢。此外,它要求您为整个交互打开一个事务,如果您有一个跨越多个请求的业务事务,这是不切实际的。如果您需要跟踪已读取的对象以避免不一致的读取,情况会更糟。

工作单元跟踪您在可能影响数据库的业务事务期间所做的一切。完成后,它会计算出根据您的工作更改数据库需要做的所有事情。

每当我为客户端使用实体框架(我承认这种情况很少见)时,ObjectContext 对象就是系统的工作单元实现。那就是ObjectContext会有点满足上面的三个说法。与其过分关注使用 ObjectContext 的绝对正确定义,不如让事情变得更容易一些。

对 DI/IoC 和存储库模式进行一些研究,这将使您在处理问题时更加灵活。

于 2010-08-01T12:25:54.500 回答