在单个LINQ语句中加载父记录及其子记录

在单个LINQ语句中加载父记录及其子记录,linq,linq-to-sql,eager-loading,Linq,Linq To Sql,Eager Loading,我知道对数据库进行两次点击就可以轻松完成这项工作,但我一直在尝试使用一条LINQ语句来加载order by ID及其order项,同时将它们转换为ViewModel对象: var query = from orderLine in db.PurchaseOrderLines where orderLine.PurchaseOrderId == id orderby orderLine.Id group orderLine b

我知道对数据库进行两次点击就可以轻松完成这项工作,但我一直在尝试使用一条LINQ语句来加载order by ID及其order项,同时将它们转换为ViewModel对象:

var query = from orderLine in db.PurchaseOrderLines
            where orderLine.PurchaseOrderId == id
            orderby orderLine.Id
            group orderLine by orderLine.PurchaseOrder into grouped
            select new PurchaseOrderViewModel
            {
                Id = grouped.Key.Id,
                PlacedDateTime = grouped.Key.PlacedDateTime,
                Reference = grouped.Key.OrderReference,
                StatusId = grouped.Key.PurchaseOrderStatusId,
                Status = grouped.Key.PurchaseOrderStatus.Description,
                Supplier = grouped.Key.Supplier.Name,
                SupplierId = grouped.Key.SupplierId,
                OrderLines = grouped.Select(row => new PurchaseOrderLineViewModel
                {
                    Id = row.Id,
                    PartNumber = row.Product.PartNumber,
                    ProductDescription = row.Product.Description,
                    Quantity = row.Quantity
                })
            };
但是,查询类型为System.Data.Objects.ObjectQuery,尝试迭代结果会引发异常:

System.InvalidOperationException was unhandled by user code
  Message=Sequence contains no elements
  Source=System.Core
  StackTrace:
       at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
       at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3[TResult](IEnumerable`1 sequence)
       at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
       at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
       at System.Linq.Queryable.Single[TSource](IQueryable`1 source)
       at MyApp.Controllers.PurchaseOrderController.Details(Int32 id) in E:\Code\WCs\MyApp\MyApp\Controllers\PurchaseOrderController.cs:line 69
       at lambda_method(Closure , ControllerBase , Object[] )
       at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
       at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
  InnerException: 
我做错了什么?我这样做是不是犯了错误


非常感谢。

您有几个选项可以强制在LINQ to SQL中进行即时加载。如果不知道您是如何执行查询的,或者是否正在实现分页等等,就很难说了

在现有查询中,我要尝试的第一件事是在执行查询时强制订单行进入新列表,如下所示:

OrderLines = grouped.Select(row => new PurchaseOrderLineViewModel
{
    Id = row.Id,
    PartNumber = row.Product.PartNumber,
    ProductDescription = row.Product.Description,
    Quantity = row.Quantity
}).ToList()
如果这行得通,那就简单了

另一种方法是使用DataLoadOptions类。这是在LINQtoSQL中实现即时加载的常用方法

var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<PurchaseOrder>(p => p.PurchaseOrderLines);
db.LoadOptions = loadOptions;

唯一需要注意的是,在使用上下文之前,需要设置datacontext的LoadOptions属性。如果您在短期内以推荐的方式使用上下文(每个操作一个实例),这应该不会是一个问题,但是这种使用模式似乎不像预期的那样普遍。如果您创建一个datacontext并将其传递或保留,那么这可能会给您带来问题。

您有几个选项可以强制在LINQ to SQL中进行即时加载。如果不知道您是如何执行查询的,或者是否正在实现分页等等,就很难说了

在现有查询中,我要尝试的第一件事是在执行查询时强制订单行进入新列表,如下所示:

OrderLines = grouped.Select(row => new PurchaseOrderLineViewModel
{
    Id = row.Id,
    PartNumber = row.Product.PartNumber,
    ProductDescription = row.Product.Description,
    Quantity = row.Quantity
}).ToList()
如果这行得通,那就简单了

另一种方法是使用DataLoadOptions类。这是在LINQtoSQL中实现即时加载的常用方法

var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<PurchaseOrder>(p => p.PurchaseOrderLines);
db.LoadOptions = loadOptions;
唯一需要注意的是,在使用上下文之前,需要设置datacontext的LoadOptions属性。如果您在短期内以推荐的方式使用上下文(每个操作一个实例),这应该不会是一个问题,但是这种使用模式似乎不像预期的那样普遍。如果您创建一个datacontext并将其传递或保留,那么这可能会给您带来问题