我正在为应用程序编写数据访问层.访问层广泛使用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(); }
这是一个粗略的过度简化,但它给出了一般的想法.有没有更好的方法来处理这种模式?每次我想访问数据库时,我是否应该实例化新的数据上下文?
它实际上并不重要.我刚才问过LINQ to SQL团队的Matt Warren,这是答案:
我们实现IDisposable有几个原因:
如果应用程序逻辑需要保留超出预期使用DataContext或有效的实体,则可以通过调用Dispose来强制执行该合同.该实体中的延迟加载器仍将引用DataContext,并且如果任何代码尝试导航延迟属性,则会尝试使用它.这些尝试将失败.Dispose还强制DataContext转储其物化实体的缓存,以便单个缓存实体不会意外地保持通过该DataContext实现的所有实体,否则会导致看起来像是内存泄漏.
可以欺骗自动关闭DataContext连接的逻辑,使连接保持打开状态.DataContext依赖于枚举查询的所有结果的应用程序代码,因为到结果集的末尾会触发连接关闭.如果应用程序使用IEnumerable的MoveNext方法而不是C#或VB中的foreach语句,则可以提前退出枚举.如果您的应用程序遇到连接未关闭的问题,并且您怀疑自动关闭行为不起作用,则可以使用Dispose模式作为解决方法.
但基本上你不真的需要在大多数情况下处理掉-这是由设计.我个人比较喜欢这样做反正,因为它更容易跟随比记住异常的负荷,它"它实现IDisposable的一切处置"的规则-但你不可能泄漏的资源,如果你不忘记处置它.
将您的datacontext视为资源.并且使用资源的规则说
"尽可能晚地获取资源,尽快释放它"
DataContext非常轻量级,适用于工作单元应用程序.但是,我不认为我会将DataContext保留在我的对象中.如果您不打算使用设计器生成的代码来管理业务对象,则可能需要查看存储库模式.存储库模式将允许您使用与数据上下文分离的对象,然后在进行更新之前重新附加它们等.
就个人而言,我能够在大多数情况下使用DBML设计器生成的代码,并为我的业务和验证逻辑提供部分类实现.我还使设计器生成的数据上下文抽象并从中继承,以允许我拦截诸如直接添加到数据上下文并在那里应用业务逻辑的存储过程和表值函数方法之类的东西.
我在ASP.NET MVC中使用的模式是注入一个工厂类,该工厂类根据工作单元的需要创建适当的数据上下文.使用工厂允许我通过以下方式合理地模拟数据上下文:(1)使用现有数据上下文类的包装器使其可模拟(模拟包装器,因为DataContext不容易模拟)和(2)创建假/模拟上下文和工厂来创造它们.能够从工厂随意创建它们使得我不必长时间保持一个.