EF 7 包含一个带有 where 子句的集合,然后包括一个下一级的集合
本文关键字:集合 包括一 一级 然后 where 子句 EF 包含一 | 更新日期: 2023-09-27 18:35:27
我正在尝试使用 EF 7 查询集合和子集合。代码如下:
var customerID = 86795;
var query = await _context.Contacts
.Where(g => g.CustomerID == customerID )
.Include(g => g.Address.Where(p => p.AddressTypeID == 1))
.ThenInclude(p=> p.City)
.ToListAsync();
> Error CS1061 'IEnumerable<Address>' does not contain a definition for
> 'City' and no extension method 'City' accepting a first argument of
> type 'IEnumerable<Address>' could be found (are you missing a using
> directive or an assembly reference?) Contacts.DNX 4.5.1, Contacts.DNX
> Core 5.0
当我只是使用
var customerID = 86795;
var query = await _context.Contacts
.Where(g => g.CustomerID == customerID )
.Include(g => g.Address)
.ThenInclude(p=> p.City)
.ToListAsync();
但这将加载客户的所有地址,我只想要 AddressTypeID 为 1 的最近地址。
知道怎么做吗?
您可以尝试匿名投影,这会将您的查询转换为 SQL。
var customerID = 86795;
var query = await _context.Contacts
.Where(g => g.CustomerID == customerID)
.Select(cntct=> new
{
contact = cntct,
address = cntct.Address.Where(p => p.AddressTypeID == 1),
city = cntct.Address.Where(p => p.AddressTypeID == 1)
.Select(h=>h.City),
}.ToList();
无法在"包含"中进行筛选。在任何版本的实体框架中。
如果需要加载集合的子集,则需要使用 Join 而不是使用导航属性,并在需要使用 Where 子句进行筛选
像这样(简化,可读性的额外步骤):
var filteredAddresses = Addresses.Where(x=>x.AddressTypeId==1);
var customersWithAddress = Customers.Join(filteredAddresses, x=>x.Id,x=>x.CustomerId,(c,a)=> new {
Customer=c,
Address=a
});
或者,如果需要单个客户,假设您在"地址"中具有"客户"导航属性:
var addressWithCustomer = Addresses
.Where(x=>x.AddressTypeId==1 && x.CustomerId == customerId)
.Include(x=>x.Customer)
.Include(x=>x.City)
.Single();
很多时候,最好处理涉及条件嵌套实体的查询,从嵌套实体开始,将条件应用于此嵌套的同伴,然后投影出父实体,因为从嵌套的可枚举实体访问父实体总是更容易。(多对一)
在我们的例子中,我们可以在地址实体上应用过滤器,然后在联系人实体上对其进行分组。
var customerID = 86795;
var query = await _context.Addresses
.Where(a => a.Contact.CustomerID == customerID
&& a.Contact.RegistrationDate.Year == 2016
&& a.AddressTypeID == 1)
.Include(a => a.Contact)
.Include(a => a.City)
.GroupBy(a => a.Contact)
.Take(20) // by the way, you should apply some orderby for a predicatble Take
.ToListAsync();
如果您绝对想要联系人列表作为上述查询的输出,则可以执行此操作。
var contacts = query.Select(g =>
{
g.Key.Addresses = g.ToList();
return g.Key;
}).ToList();
// now you can work off the Contacts list, which has only specific addresses
这基本上将为您提供具有CustomerID的所有联系人的分组列表,并且仅具有这些地址类型和注册年份。这里重要的是遍历组以获取地址,而不是使用分组。键地址导航。(分组。键将是联系人实体)
另外,我不知道 CustomerID 是否是联系人实体上的主键,但如果是,看起来您只需要一个联系人的匹配地址列表。在这种情况下,查询将是:
var query = await _context.Addresses
.Where(a => a.Contact.CustomerID == customerID && a.AddressTypeID == 1)
.Include(a => a.Contact)
.Include(a => a.City)
.ToListAsync();
包括预先加载的集合,然后使用 Any 而不是 Where ...以选择所需实体的子项中的特定项。
var customerID = 86795;
var query = await _context.Contacts
.Where(g => g.CustomerID == customerID )
.Include(g => g.Address.Any(p => p.AddressTypeID == 1))
.ThenInclude(p=> p.City)
.ToListAsync();