在不中断延迟执行代码的情况下处理DataContext/ObjectContext
本文关键字:处理 情况下 DataContext ObjectContext 代码 中断 延迟 执行 | 更新日期: 2023-09-27 18:01:16
Joseph Albahari和Ben Albahari(O’Reilly(的《坚果壳中的C#6.0》。
版权所有2016 Joseph Albahari和Ben Albahari,978-1-491-92706-9。
在第376页,对处理DataContext
/ObjectContext
实例进行了讨论。
处理DataContext/ObjectContext
尽管DataContext/ObjectContext实现了IDisposable,但您可以(在general(在不处理实例的情况下逃脱。处置力上下文与dispose的连接,但这通常是不必要的因为L2S和EF在您完成时会自动关闭连接从查询中检索结果。处理上下文实际上可以因为懒惰的评估而有问题。考虑以下内容:
IQueryable<Customer> GetCustomers (string prefix) { using (var dc = new NutshellContext ("connection string")) return dc.GetTable<Customer>() .Where (c => c.Name.StartsWith (prefix)); } ... foreach (Customer c in GetCustomers ("a")) Console.WriteLine (c.Name);
这将失败,因为我们枚举时会评估查询它——这是在处理其DataContext之后。
不过,有一些关于不处理上下文的注意事项。
(然后列出了它们…(
最后,为了避免刚才描述的异常,它指出:
如果要显式处理上下文,则必须传递
DataContext/ObjectContext
实例转换为方法,例如GetCustomers
以避免所描述的问题。
问题:
我不明白作者的意思。(没有举例说明(。
我的意思是,作者说你可以让方法仍然返回一个IQueryable<Customer>
,处理掉DataContext
参数并完全保留deferred execution
吗?
这是如何实现的?只有放弃懒惰的加载,我才能看到它的发生。
懒惰加载的概念和存储库模式之间存在冲突。DataContext/ObjectContext是为其设计的存储库模式,它将访问数据库的代码与使用业务对象的代码分开。
延迟加载属性的根本问题是,数据层返回的业务对象依赖于并利用技术特定的数据检索,而这可能不是预期的。
一些例子:
当稍后尝试访问延迟加载属性时,底层数据检索机制已被丢弃。这就是作者试图解释的。
Customer myCustomer;
using (var dataSource = GetRepository()) {
myCustomer = dataSource.Retrieve("John");
}
// throws exception since the connection to
// the database has been closed already
var orders = myCustomer.Orders;
用户界面中的某个地方可能有代码,试图从某个属性中读取,这会触发数据库调用并降低用户界面的速度。SqlException
可能会在意外的位置检索属性,从而导致数据存储和使用者代码之间的不可靠性或紧密耦合。
// some business layer
Customer myCustomer = myRepository.GetCustomer("John");
...
// some UI component trying to show the customer's orders
var orders = myCustomer.Orders;
// could throw any kind of data access exception, such as SqlException
// e.g. Wifi is not working anymore, now I have to build error
// handling for that here, even though it's not very obvious to someone
// who is just accessing the Orders property
请注意,在我看来,这比数据层和逻辑层之间的显式耦合更糟糕,因为耦合是存在的,但隐藏在视图之外。
这意味着您应该创建一次数据上下文对象,并将其传递给查询方法以供使用。
类似于:
IQueryable<Customer> GetCustomers (NutshellContext dc, string prefix)
{
return dc.GetTable<Customer>()
.Where (c => c.Name.StartsWith (prefix));
}
然后,当您调用该方法时,传入您创建的数据上下文。您应该只在关闭时处理该上下文。