有两种类型的 LINQ 函数:使用延迟执行的函数和不使用延迟执行的函数。
使用延迟执行的函数(Where、Select、GroupBy、Join、...)仅更改 IQueryable 的表达式。只有在调用 ToList()、Any()、FirstOrDefault() 等非延迟函数后,才会真正执行查询。
异步版本仅对非延迟函数有用。毕竟,你的线程可以做一些其他事情,而不是等待来自数据库的结果。
幸运的是,DbSet 有可等待的异步扩展函数。你可以使用它们。
但是,如果您设置了many-to-many relationship according to entity-framework default conventions,您的查询将非常容易。
class Equipment
{
public int Id {get; set;}
...
// every equipment has zero or more Components (many-to-many)
public virtual ICollection<Component> Components {get; set;}
}
class Component
{
public int Id {get; set;}
public string Name {get; set;}
// Every Component belongs to zero or more Equipments (many-to-many)
public virtual ICollection<Equipment> Equipments {get; set;}
}
class MyDbcontext : DbContext
{
public DbSet<Equipment> Equipments {get; set;}
public DbSet<Component> Components {get; set;}
}
这就是 Entity Framework 需要知道的所有内容,才能理解您想要设计多对多关系。您不必提及 EquipmentComponent 表。实体框架会理解它的需要并为你创建它。
返回您的查询
您想要属于 ID 等于设备 ID 的设备的所有组件的所有 ComponentIds 和 ComponentNames
正确设置多对多后,您可以使用 ICollections 获取数据:
var result = dbContext.Equipments // from all equipment
.Where(equipment => equipment.Id == equipmentId) // take only those with equipmentId
.SelectMany(equipment => equipment.Components // from their components
.Select(component => new
{
Id = component.Id, // select the Id
Name = component.Name, // and the Name
}));
这样的结果仍然是一个 IQueryable。尚未与数据库进行通信。要执行异步查询,您必须使用非延迟函数
public async Task<IEnumerable<Component>>
GetComponentsByEquipmentIdAsync(int equipmentId)
{
using (var dbContext = new MyDbContext())
{
var result = ... // see above
return await result.ToListAsync();
}
}
如果您确实更喜欢偏离标准实体框架的多对多约定,并且您不想使用 ICollections,而是设计自己的联接,那么您必须自己做。
使用 linq 方法语法的内连接没有问题,但是如果你连接三个表,内连接看起来很可怕。 See How to perform multiple tables using lambda expressions
因此,我将使用查询语法来创建 IQueryable,然后使用异步函数获取结果:
public async Task<IEnumerable<Component>> GetComponentsByEquipmentIdAsync (int equipmentId)
{
using (var dbContext = new MyDbContext())
{
var result = from equipment in dbContext.Equipments
.Where(equipment => equipment.Id == equipmentId)
join equipmentmodel in dbContext.EquipmentModel
on equipment.Id equals equipmentModel.EquipmentId
join model in dbContext.Models
on equipmentmodel.ModelId equals model.Id
select new
{
Id = component.Id,
Name = component.Name
};
return await result.ToListAsync(); // or whatever non-deferred you want
}