在不中断延迟执行代码的情况下处理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

懒惰加载的概念和存储库模式之间存在冲突。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));
}

然后,当您调用该方法时,传入您创建的数据上下文。您应该只在关闭时处理该上下文。