我有很多包含的查询,我想知道我是否可以对某些包含进行攻击。
例如,这是我的一个查询,其中(非法)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?
答案 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
)以添加更多含义。