在方法中处理DataContext的最佳LINQ-to-SQL策略是什么?

时间:2009-11-05 13:39:12

标签: c# linq-to-sql datacontext

我理解在从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;
}

2 个答案:

答案 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;