Linq承担包括?

时间:2013-09-15 22:25:46

标签: c# linq entity-framework

我有很多包含的查询,我想知道我是否可以对某些包含进行攻击。

例如,这是我的一个查询,其中(非法)Take说明了我想要做的事情。

var primaryLocation = context.Locations
                .Include("PhoneNumbers")
                .Include("Invoices").Take(50)
                .Include("Invoices.Items")
                .Include("Schedules")
                .Include("Staffs")
                .SingleOrDefault(d => d.Id == locationId);

目前我能想到的唯一方法就是这样:

var primaryLocation = context.Locations
                .Include("Invoices")
                .Include("Etc")
                .SingleOrDefault(d => d.Id == locationId);

primaryLocation.Invoices = primaryLocation.Invoices.Take(50).ToList();

我不希望这样做,因为这意味着从数据库中撤回整个发票清单,这是我不需要的。

有没有方便的方法来构建Take in my query?

2 个答案:

答案 0 :(得分:0)

似乎对你正在做的事情有两个相互矛盾的标准。我在这里猜测,但你没有给我们留下太多的东西。

由于您的primaryLocation.Invoices = primaryLocation.Invoices.Take(50).ToList();语句仅使用了您的1个,因此我假设您使用primaryLocation做的事情比您向我们展示的更多。这让我相信你希望primaryLocation包含所有的东西。然后你似乎不想超过那些50,所以这毕竟不是所有的东西......对我来说这是一个矛盾。如果你需要全部,你应该把它全部包括在内。

如果您想特别选择50张发票,可以在自己的查询中单独选择。我自己使用NHibernate,所以我不确定实体框架中未来的语法,但是如果你想要服务器只需1次往返就可以要求多个东西,在NHibernate中你可以对期货进行一系列的查询允许这个。我希望实体框架有类似的东西。

简而言之,我所建议的是,如果你想让primaryLocation包含你的所有数据,那么你就会得到什么,如果你在使用像Take这样的过滤器获取更具体的信息,那么你可能想要更具体地查询。

答案 1 :(得分:0)

如果您不想要所有内容,请使用投影而不是盲目地调用Include

var primaryLocation = context.Locations
    .Select(location => new {
        Id = location.Id,
        Name = location.Name,
        // ... other properties needed on the front end
        RecentInvoices = location.Invoices
            // really should sort if you're only taking 50
            .OrderByDescending(invoice => invoice.CreatedAt)
            .Take(50),
        AllPhoneNumbers = location.PhoneNumbers,
    })
    .SingleOrDefault(location => location.Id == locationId);

您可以使用投影来获取您需要的发票信息,我只是不想让示例过于复杂。

使用此方法可以获得所需的数据,而不会产生混淆。它还允许您为您的属性命名(例如上面的RecentInvoices)以添加更多含义。