在方法中处理 DataContext 的最佳 LINQ-to-SQL 策略是什么?
据我所知,从 LINQ-to-SQL 类获取数据时使用 using
块是一种很好的做法,如下所示。
但是,当我这样做时,我只能访问 orders
的浅层属性(例如 Order.OrderId
),而不能访问更深层次的属性(例如 Customer.CustomerName< /code>),因为此时它们似乎已被处理掉。
我可以取出我的 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;
}
I understand that it is good practice to use a using
block when getting data from the LINQ-to-SQL classes as shown below.
However, when I do this, I can only access the shallow properties of orders
(e.g. Order.OrderId
) but not the deeper properties (e.g. Customer.CustomerName
) since they seem to be disposed of at this point.
I can take out my using
block which allows me to access Customers, but this does not free the resources.
What is the best practice here?
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;
}
}
}
}
Answer:
Thanks Adam, using your suggestion I got my code to work like this:
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
无法访问该对象的更深层次属性,因为 LINQ-to-SQL 使用延迟加载(也就是说,它会根据需要自动检索这些记录,因此当您第一次访问它们时,它会执行数据库操作)。由于
DataContext
已被释放,因此它无法执行必要的数据库操作。可以“急切地”加载这样的属性(意味着在初始检索时),但您必须预先了解所有这些。一般来说,您的
DataContext
应在您的工作单元的持续时间内有效,因此此处显示您的DataContext
需要在这个方法并传入(或者甚至声明为DataContext
上的扩展方法)。这是关于
DataContext
博客文章 > 生命周期管理。The deeper properties of the object can't be accessed because LINQ-to-SQL uses lazy loading (that is, it automatically retrieves those records as needed, so when you access them for the first time it performs a database operation). Because the
DataContext
is disposed, it can't perform the necessary database operations. It is possible to have properties like this loaded "eagerly" (meaning at the time of initial retrieval), but you'll have to know all of these up front.In general, your
DataContext
should live for the duration of your unit of work, so it appears here that yourDataContext
needs to be declared outside of this method and passed in (or even declared as an extension method on yourDataContext
).Here is a good blog post on
DataContext
lifetime management.如果您知道您想要获取客户,则可以在 DataLoadOptions 中指定这一点,它将连接请求以急切地加载它们,而不是延迟加载它们。
这是有关 DataLoadOptions 的 msdn 文章。
例子:
If you know for a fact that you're going to want to get Customers, you can specify that in the DataLoadOptions and it will wire up the request to eagerly load them instead of lazily loading them.
Here's the msdn article on DataLoadOptions.
Example: