我理解在从LINQ-to-SQL类获取数据时使用using
块是一个好习惯,如下所示。
然而,当我这样做时,我只能访问orders
的浅层属性(例如Order.OrderId
)而不能访问更深层的属性(例如Customer.CustomerName
),因为它们似乎被处置掉了在这一点上。
我可以取出允许我访问客户的using
块,但这不会释放资源。
这里的最佳做法是什么?
using System;
using System.Collections.Generic;
using System.Linq;
using TestExtn2343.Models;
namespace TestExtn2343
{
class Program
{
public static void Main(string[] args)
{
var orders = GetOrders(10, 10);
orders.ForEach(x =>
{
Customer customer = x.Customer;
if (customer != null)
{
//SUCCEEDS:
Console.WriteLine("{0}, {1}", x.OrderID);
//FAILS: "
Console.WriteLine("{0}, {1}", x.OrderID, x.Customer.ContactName.ToString());
}
});
Console.ReadLine();
}
public static List<Order> GetOrders(int skip, int take)
{
using (MainDataContext db = new MainDataContext())
{
List<Order> orders = (from order in db.Orders
select order).Skip(skip).Take(take).ToList();
return orders;
}
}
}
}
感谢Adam,使用您的建议我让我的代码像这样工作:
public static void Main(string[] args)
{
using (MainDataContext db = new MainDataContext())
{
GetOrders(db, 10, 10).ForEach(x => Console.WriteLine("{0}, {1}", x.OrderID, x.Customer.ContactName.ToString()));
}
Console.ReadLine();
}
public static List<Order> GetOrders(MainDataContext db, int skip, int take)
{
List<Order> orders = (from order in db.Orders
select order).Skip(skip).Take(take).ToList();
return orders;
}
答案 0 :(得分:4)
无法访问对象的更深层属性,因为LINQ-to-SQL使用延迟加载(也就是说,它会根据需要自动检索这些记录,因此当您第一次访问它们时它执行数据库操作的时间)。由于DataContext
已被释放,因此无法执行必要的数据库操作。这样的属性可能会“热切地”加载(意味着在初始检索时),但你必须事先了解所有这些。
一般情况下,您的DataContext
应在您的工作单元期间生效,因此此处显示您的DataContext
需要在此方法之外声明,传入(或甚至在DataContext
上声明为扩展方法。)
DataContext
有关{{1}}终身管理的好blog post。
答案 1 :(得分:1)
如果你知道你想要获得客户的事实,你可以在DataLoadOptions中指定它,它会将请求连接起来,急切地加载它们而不是懒得加载它们。
这是msdn article on DataLoadOptions。
示例:
var dlo = new DataLoadOptions();
dlo.LoadWith<Order>(o => o.Customer);
context.DataLoadOptions = dlo;