约瑟夫·阿尔巴哈里和本·阿尔巴哈里(奥莱利)在果壳中的C#6.0。版权所有2016 Joseph Albahari和Ben Albahari,978-1-491-92706-9。
在第376页讨论了如何处置DataContext
/ ObjectContext
个实例。
处理DataContext / ObjectContext
虽然DataContext / ObjectContext实现了IDisposable,但你可以(在 general)在没有处理实例的情况下离开。处置力量 context与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
吗?
这是如何实现的?只有放弃延迟加载,我才能看到它发生。
答案 0 :(得分:1)
延迟加载的概念与Repository pattern之间存在冲突。 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;
您可能在UI中的某个位置尝试从某个属性读取代码,这会触发数据库调用并降低UI的速度。 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
请注意,在我看来,这比在数据和逻辑层之间明确耦合更差,因为耦合在那里,但是从视图中隐藏。
答案 1 :(得分:0)
它说你应该创建一次数据上下文对象并将其传递给查询方法以供使用。
类似的东西:
IQueryable<Customer> GetCustomers (NutshellContext dc, string prefix)
{
return dc.GetTable<Customer>()
.Where (c => c.Name.StartsWith (prefix));
}
然后,当您调用该方法时,传入您创建的数据上下文。您应该只在关闭时处置该上下文。