LINQ to SQL:映射关联的子集

时间:2009-01-09 10:35:35

标签: .net linq linq-to-sql

在我们最初的开发过程中,我们并不担心扩展问题,只是让系统的骨架充满凝聚力。

我们现在正在研究精炼屏幕,其中记录的数量将变得太大而无法显示。例如,我们有一个页面用于显示当前涉及显示所有Parent记录的Child的详细信息。这是通过调用Children对象上的Parent属性来完成的(我们正在尝试开发一个富域)。我们希望将其更改为RecentChildren

问题是我无法以任何方式找到限制EntitySet返回的记录的方法。您可以对EntitySet执行查询,但它会从数据库中检索所有Children,然后使用LINQ to Objects对其进行过滤。显然这是非常低效的。

我们可以重新构建代码以删除Children属性的映射并从服务中检索它们,但我们希望尽可能保持域中的关联。

有没有办法解决这个问题,还是我们必须要看一下不同的ORM,例如NHibernate?

3 个答案:

答案 0 :(得分:3)

blogging about我的LINQ to SQL问题之后,一个名叫Anders的人向我指出了解决这个问题的方向。利用DataLoadOptions.AssociateWith

答案 1 :(得分:1)

那么,您可以直接使用导航属性 - 即直接使用父ID并从子集中选择?

int id = parent.ParentID;
var qry = from child in db.Children
          where child.ParentID = id && child.Date > whatever
          select child;

我还怀疑使用查询中的导航属性进行SelectMany会有效:

using System;
using System.Linq;
using ConsoleApplication5;


class Program
{
    static void Main(string[] args)
    {
        string id;
        using (var ctx = new DataClasses1DataContext())
        {
            id = ctx.Customers.Select(x => x.CustomerID).First();
        }
        DateTime cutoff = DateTime.Today.AddMonths(-2);

        using (var ctx = new DataClasses1DataContext())
        {
            // parent id
            ctx.Log = Console.Out;
            var qry = from o in ctx.Orders
                      where o.CustomerID == id
                        && o.OrderDate > cutoff
                      select o;
            foreach (var order in qry)
            {
                Console.WriteLine(order.OrderID);
            }
        }

        using (var ctx = new DataClasses1DataContext())
        {
            // navigation property in query
            ctx.Log = Console.Out;
            var qry = from c in ctx.Customers
                      where c.CustomerID == id
                      from o in c.Orders
                      where o.OrderDate > cutoff
                      select o;
            foreach (var order in qry)
            {
                Console.WriteLine(order.OrderID);
            }
        }
    }
}

TSQL(对不起格式 - 控制台转储!):

SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE ([t0].[CustomerID] = @p0) AND ([t0].[OrderDate] > @p1)
-- @p0: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [ALFKI]
-- @p1: Input DateTime (Size = 0; Prec = 0; Scale = 0) [09/11/08 00:00:00]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1

SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [
t1].[RequiredDate], [t1].[ShippedDate], [t1].[ShipVia], [t1].[Freight], [t1].[Sh
ipName], [t1].[ShipAddress], [t1].[ShipCity], [t1].[ShipRegion], [t1].[ShipPosta
lCode], [t1].[ShipCountry]
FROM [dbo].[Customers] AS [t0], [dbo].[Orders] AS [t1]
WHERE ([t1].[OrderDate] > @p0) AND ([t0].[CustomerID] = @p1) AND ([t1].[Customer
ID] = [t0].[CustomerID])
-- @p0: Input DateTime (Size = 0; Prec = 0; Scale = 0) [09/11/08 00:00:00]
-- @p1: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [ALFKI]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1

请注意,在这两种情况下,日期条件都会下降到数据库。

答案 2 :(得分:0)

将RecentChildren属性添加到Parent分部类。不要将其实现为EntitySet。