何时应该处理数据上下文
何时应该处理数据上下文
我正在为一个应用程序编写数据访问层。该访问层广泛使用Linq类来返回数据。目前,为了将数据反映到数据库中,我已经添加了一个私有的数据上下文成员和一个公共的保存方法。代码大致如下:
private DataContext myDb; public static MyClass GetMyClassById(int id) { DataContext db = new DataContext(); MyClass result = (from item in db.MyClasss where item.id == id select item).Single(); result.myDb = db; return result; } public void Save() { db.SubmitChanges(); }
这只是一个非常简单的概述,但它给出了一般的想法。有没有更好的处理这种模式的方法?每次访问数据库时,我应该实例化一个新的数据上下文吗?
当应该处理数据上下文的问题出现时,可能的原因是在对象中保留DataContext,而解决方法是使用仓储模式或工厂类。
DataContext是相当轻量级的,适用于工作单元应用程序。但是,我不认为我会在对象中保留DataContext。如果您不使用设计生成的代码来管理业务对象,您可能需要考虑使用仓储模式。仓储模式允许您在与数据上下文分离的情况下操作对象,然后在执行更新等操作之前重新附加它们。
就个人而言,我大部分时间都能使用DBML设计生成的代码,使用部分类实现我的业务和验证逻辑。我还将设计生成的数据上下文设置为抽象的,并从中继承,以允许我拦截直接添加到数据上下文的存储过程和表值函数方法,并在那里应用业务逻辑。
在ASP.NET MVC中,我使用的一种模式是通过注入一个工厂类根据需要创建适当的数据上下文来处理工作单元。使用工厂可以使我相对容易地模拟数据上下文,方法是(1)使用包装现有数据上下文类的包装器使其可以模拟(模拟包装器,因为DataContext不容易模拟),以及(2)创建伪造/模拟上下文和工厂来创建它们。能够随时从工厂创建它们使得我不必长时间保留一个上下文。
我的目标是设置好,以便只有使用对象与数据库进行交互的人才能使用Save()
方法。仓储模式是否实现了这一目标?您有一些示例的链接可以说明您在这里的意思吗?
当应用程序逻辑需要在数据上下文(DataContext)被使用或有效之后仍然保存实体时,可以通过调用Dispose方法来强制执行该合同。如果在该实体中存在延迟加载器(deferred loaders),则这些延迟加载器仍然会引用数据上下文并在任何代码尝试导航延迟属性时尝试使用它。这些尝试将失败。Dispose还会强制DataContext清除其缓存的已实例化实体,以防止单个缓存的实体意外保持所有通过该DataContext实例化的实体的存活状态,否则会导致看似的内存泄漏。
另外,数据上下文(DataContext)依赖于应用程序代码枚举查询的所有结果来关闭连接。如果应用程序使用IEnumerable的MoveNext方法而不是C#或VB中的foreach语句,则可能会过早退出枚举。如果应用程序在连接未关闭时遇到问题,并怀疑自动关闭行为不起作用,可以使用Dispose模式作为解决方法。
但基本上在大多数情况下,你实际上并不需要销毁它们,这是设计上的考虑。个人而言,我仍然喜欢这样做,因为遵循“销毁所有实现IDisposable的对象”规则比记住一堆例外情况更容易,但如果你忘记销毁它,你不太可能泄漏资源。
至于新的DbContext类是否适用于这个答案,我不确定,我不会假设它适用。
根据引用的文本,我得出的结论实际上是,当你完成使用数据上下文时,应该始终立即释放它,而不是说“并不太重要”。因为选择是:A) 想知道编码人员是否会遇到Matt Warren描述的这两种昂贵的问题,或者B) 只是有一个调用IDisposable的Dispose方法的总体规则。我发现B更容易,特别是对于大型团队。
当应该丢弃数据上下文?
在编写代码时,将数据上下文视为资源是一个很好的想法。使用资源的规则是“尽可能晚地获取资源,尽快释放资源”。但是,有些情况下你不能立即处理它以进行延迟加载。在这种情况下,你可以不进行处理而不会面临严厉的惩罚。
为什么会出现这个问题?
数据上下文在处理数据库操作时是必需的。通常情况下,我们会尽早创建和处理数据上下文,以便在不需要时及时释放资源。然而,有些情况下,我们需要延迟加载数据,这时就不能立即释放数据上下文。这就导致了问题的出现。
解决方法:
一种解决方法是使用using语句来处理数据上下文。使用using语句可以确保在使用完数据上下文后及时释放资源。例如:
using (var context = new DataContext()) { // 使用数据上下文进行数据库操作 }
另一种解决方法是等到不再使用数据上下文时再进行释放。这可以通过手动调用Dispose方法来实现。例如:
var context = new DataContext(); // 使用数据上下文进行数据库操作 context.Dispose();
这种方法适用于需要延迟加载数据的情况。但需要注意的是,在使用完数据上下文后,确保调用Dispose方法来释放资源。
在编写代码时,将数据上下文视为资源是一个很好的实践。然而,有些情况下,我们需要延迟加载数据,这就导致了不能立即释放数据上下文的问题。为了解决这个问题,我们可以使用using语句来确保及时释放资源,或者手动调用Dispose方法来释放数据上下文。无论采用哪种方法,都要确保在不再使用数据上下文时及时释放资源。