C# 我应该什么时候处理数据上下文
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/389822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should I dispose of a data context
提问by Mykroft
I'm currently writing a data access layer for an application. The access layer makes extensive use of linq classes to return data. Currently in order to reflect data back to the database I've added a private data context member and a public save method. The code looks something like this:
我目前正在为应用程序编写数据访问层。访问层广泛使用 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();
}
That's a gross over simplification but it gives the general idea. Is there a better way to handle that sort of pattern? Should I be instantiating a new data context every time i want to visit the db?
这是一个粗略的简化,但它给出了一般的想法。有没有更好的方法来处理这种模式?每次我想访问数据库时,我都应该实例化一个新的数据上下文吗?
采纳答案by Jon Skeet
It actually doesn't matter too much. I asked Matt Warren from the LINQ to SQL team about this a while ago, and here's the reply:
其实也没有太大关系。不久前,我向 LINQ to SQL 团队的 Matt Warren 询问了这个问题,以下是答复:
There are a few reasons we implemented IDisposable:
If application logic needs to hold onto an entity beyond when the DataContext is expected to be used or valid you can enforce that contract by calling Dispose. Deferred loaders in that entity will still be referencing the DataContext and will try to use it if any code attempts to navigate the deferred properties. These attempts will fail. Dispose also forces the DataContext to dump its cache of materialized entities so that a single cached entity will not accidentally keep alive all entities materialized through that DataContext, which would otherwise cause what appears to be a memory leak.
The logic that automatically closes the DataContext connection can be tricked into leaving the connection open. The DataContext relies on the application code enumerating all results of a query since getting to the end of a resultset triggers the connection to close. If the application uses IEnumerable's MoveNext method instead of a foreach statement in C# or VB, you can exit the enumeration prematurely. If your application experiences problems with connections not closing and you suspect the automatic closing behavior is not working you can use the Dispose pattern as a work around.
我们实施 IDisposable 有几个原因:
如果应用程序逻辑需要在预期使用或有效 DataContext 之后保留实体,您可以通过调用 Dispose 来强制执行该合同。该实体中的延迟加载器仍将引用 DataContext 并在任何代码尝试导航延迟属性时尝试使用它。这些尝试都会失败。Dispose 还强制 DataContext 转储其物化实体的缓存,以便单个缓存的实体不会意外地使通过该 DataContext 物化的所有实体保持活动状态,否则会导致内存泄漏。
自动关闭 DataContext 连接的逻辑可能会被欺骗而使连接保持打开状态。DataContext 依赖于应用程序代码枚举查询的所有结果,因为到达结果集的末尾会触发连接关闭。如果应用程序使用 IEnumerable 的 MoveNext 方法而不是 C# 或 VB 中的 foreach 语句,则可以提前退出枚举。如果您的应用程序遇到连接未关闭的问题,并且您怀疑自动关闭行为不起作用,您可以使用 Dispose 模式作为解决方法。
But basically you don't reallyneed to dispose of them in most cases - and that's by design. I personally prefer to do so anyway, as it's easier to follow the rule of "dispose of everything which implements IDisposable" than to remember a load of exceptions to it - but you're unlikely to leak a resource if you doforget to dispose of it.
但基本上,在大多数情况下,您实际上并不需要处理它们——这是设计使然。我个人比较喜欢这样做反正,因为它更容易遵循“一切处置其实现IDisposable”,而不是记住异常的负载,以它的规则-但你不可能泄漏的资源,如果你不忘记处置它。
回答by tvanfosson
DataContext is pretty lightweight and is intended for unit of work application as you are using it. I don't think that I would keep the DataContext in my object, however. You might want to look at repository patterns if you aren't going to use the designer generated code to manage your business objects. The repository pattern will allow you to work with your objects detached from the data context, then reattach them before doing updates, etc.
DataContext 非常轻量级,适用于您正在使用的工作单元应用程序。但是,我不认为我会将 DataContext 保留在我的对象中。如果您不打算使用设计器生成的代码来管理您的业务对象,您可能需要查看存储库模式。存储库模式将允许您处理与数据上下文分离的对象,然后在进行更新等之前重新附加它们。
Personally, I'm able to live with the DBML designer generated code for the most part, with partial class implementations for my business and validation logic. I also make the designer-generated data context abstract and inherit from it to allow me to intercept things like stored-procedure and table-valued function methods that are added directly to the data context and apply business logic there.
就我个人而言,我能够忍受 DBML 设计器生成的大部分代码,以及用于我的业务和验证逻辑的部分类实现。我还将设计器生成的数据上下文抽象化并从中继承,以允许我拦截直接添加到数据上下文并在那里应用业务逻辑的存储过程和表值函数方法等内容。
A pattern that I've been using in ASP.NET MVC is to inject a factory class that creates appropriate data contexts as needed for units of work. Using the factory allows me to mock out the data context reasonably easy by (1) using a wrapper around the existing data context class so that it's mockable (mock the wrapper since DataContext is not easily mockable) and (2) creating Fake/Mock contexts and factories to create them. Being able to create them at will from a factory makes it so that I don't have to keep one around for long periods of time.
我在 ASP.NET MVC 中一直使用的一种模式是注入一个工厂类,该类根据工作单元的需要创建适当的数据上下文。使用工厂允许我通过 (1) 在现有数据上下文类周围使用包装器来模拟数据上下文相当容易,以便它是可模拟的(模拟包装器,因为 DataContext 不容易模拟)和 (2) 创建 Fake/Mock 上下文和制造它们的工厂。能够从工厂随意创建它们使我不必长时间保留它们。
回答by Perpetualcoder
Treat your datacontext as a resource. And the rule of using resource says
将您的数据上下文视为一种资源。使用资源的规则说
"acquire a resource as late as possible, release it as soon as its safe"
“尽可能晚地获取资源,在安全的情况下尽快释放它”