Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LoadWith的“深度加载”_C#_Sql_Linq - Fatal编程技术网

C# 使用LoadWith的“深度加载”

C# 使用LoadWith的“深度加载”,c#,sql,linq,C#,Sql,Linq,我有一个表结构,每个表都有一个名为ID的主键字段和与其父表的主键匹配的外键名称。因此,下表的主键出现在另一个表中,并且任何表中的第一个字段都是其主键: Category -------- CategoryID Title CategoryList ------------ CategoryListID CategoryID ListID List ---- ListID Title DataPoint --------- DataPointID RecordedDateTime

我有一个表结构,每个表都有一个名为ID的主键字段和与其父表的主键匹配的外键名称。因此,下表的主键出现在另一个表中,并且任何表中的第一个字段都是其主键:

Category
--------
CategoryID
Title


CategoryList
------------
CategoryListID
CategoryID
ListID


List
----
ListID
Title


DataPoint
---------
DataPointID
RecordedDateTime


DataPointValue
--------------
DataPointValueID
DataPointID
TheValue
以上是通过CategoryList在Category和List之间进行的多对多连接。它也是从列表到数据点、数据点到数据点值的一对多连接

使用C/LINQ并给出CategoryID值列表,我想检索:

所有附加到类别的列表条目我都有ID。对于这些列表条目,我想采用最新的1个数据点,按RecordedDateTime降序排列。从那里,我想检索附加到数据点的每个数据点值

我的LINQ是:

DBDataContext上下文=新的DBDataContextConnectionString

        context.LoadOptions = new DataLoadOptions();
        context.LoadOptions.LoadWith<DataPoint>(p => p.DataPoints.OrderByDescending(p.RecordedDataTime).FirstOrDefault());

        // this next line is how I get the list of category IDs, but don't worry about that...
        List<int> categoryIDs = (from TreeNode n in nodes
                                 select Int32.Parse(n.Value)).Distinct().ToList();

        var lists = from i in context.List
                                         join ci in context.CategoryLists on i.ListID equals ci.ListID
                                         join p in context.DataPoints on i.ListID equals p.ListID
                                         join v in context.DataPointValues on p.DataPointID equals v.DataPointID
                                         where categoryIDs.Contains(ci.CategoryID)
                                         orderby i.Title ascending
                                         select new
                                         {
                                             List = i,
                                             DataPoint = p,
                                             DataPointValues = p.DataPointValues
                                         };
但这显然不起作用-LoadWith给我带来了问题。有人能解释一下如何构造LoadWith,以便尽可能少的SQL查询来检索这个公认的大量数据吗

非常感谢,


马特。

你一个月前问过这个问题,但这里有一个答案

这里有几个问题:

在上下文上设置LoadOptions属性后,就无法更改它。您应该创建和配置DataLoadOptions对象,完成后,将其分配给上下文

LoadWith指定与父级一起自动加载的子级。因此loadOptions.LoadWithp=>p.DataPointValues将自动加载DataPoint的子级,而不是等到DataPoint.DataPointValues或任何您命名的属性被访问。LoadWith使加载成为非惰性的

AssociateWith允许您在自动加载关系的子项中筛选和排序。例如loadOptions.AssociateWithp=>p.DataPointValues.OrderByDowneringV=>v。该值将按值对DataPointValue进行排序

最后,我可能会将您的查询分为两部分,以便简化

// first setup a DataPoint -> DataPointValue relationship in your DBML
// then set up the DataPointValues to automatically load with DataPoint:

dataLoadOptions.LoadWith<DataPoint>(dp => dp.DataPointValues);

// then assign the load options to the context here

// First query
List<int> listIDs = context.CategoryLists
        .Where(cl => categoryIDs.Contains(cl.CategoryListID))
        .Select(cl => cl.ListID)
        .ToList();


// Second query(ies) - this isn't the most elegant, but simple is usually better :)
List<DataPoint> dataPoints = new List<DataPoint>();

foreach (int listID in listIDs)
{
    DataPoint foundDP = context.DataPoints
        .Where(dp => listIDs.Contains(dp.ListID))
        .OrderByDescending(dp => dp.RecordedDateTime)
        .Take(1)
        .SingleOrDefault();

        // Remember, at this point DataPointValues will already be loaded into the DataPoint

    if (foundDP != null)
        dataPoints.Add(foundDP);
}
无论如何,这是一个冗长的答案,你可能需要也可能不需要!我想这对我来说是一种练习。希望能有帮助

编辑:

对不起,我开始考虑这个

您可以更干净、更快地执行此操作:

loadOptions.LoadWith<List>(l => l.DataPoints);
loadOptions.AssociateWith<List>(l => l.DataPoints.OrderByDescending(dp => dp.RecordedDateTime).Take(1));
loadOptions.LoadWith<DataPoint>(dp => dp.DataPointValues);

// assign the LoadOptions here,     
// then:

List<DataPoint> dataPoints = context.CategoryLists
        .Where(cl => categoryIDs.Contains(cl.CategoryID))
        .Select(cl => cl.List.DataPoints)
        .ToList();