У меня есть 4 объекта, для которых я определил свойства навигации, например:
internal class ShipSet
{
[Key]
[Column("SHIPSET_ID")]
public decimal ID { get; set; }
public virtual ICollection<InstallLocation> InstallLocations { get; set; }
}
internal class InstallLocation
{
[Key]
[Column("INSTLOC_ID")]
public decimal ID { get; set; }
[Column("SHIPSET_ID")]
public decimal ShipSetID { get; set; }
public virtual ICollection<ShipSetPart> ShipSetParts { get; set; }
public virtual ShipSet ShipSet { get; set; }
}
internal class ShipSetPart
{
[Key]
[Column("PARTS_ID")]
public decimal ID { get; set; }
[Column("INSTLOC_ID")]
public decimal InstallLocationID { get; set; }
public virtual CmQueueItem CmQueueItem { get; set; }
public virtual InstallLocation InstallLocation { get; set; }
}
internal class CmQueueItem
{
[Key]
[Column("INVENTORY_ITEM_ID")]
public decimal ID { get; set; }
public virtual ICollection<ShipSetPart> ShipSetParts { get; set; }
}
У меня есть следующий свободный конфиг:
modelBuilder.Entity<CmQueueItem>().HasMany(p => p.ShipSetParts).
WithRequired(s=>s.CmQueueItem).Map(m=>m.MapKey("INVENTORY_ITEM_ID"));
modelBuilder.Entity<ShipSetPart>().HasRequired(p => p.InstallLocation);
modelBuilder.Entity<InstallLocation>().HasRequired(p => p.ShipSet);
modelBuilder.Entity<ShipSet>().HasRequired(p => p.Program);
modelBuilder.Entity<CmQueueItem>().Property(p => p.LastUpdateDate).IsConcurrencyToken();
Итак, в двух словах, у меня есть
ShipSet -> InstallLocation (от 1 до многих)
InstallLocation -> ShipSetPart (от 1 до многих)
CmQueueItem -> ShipSetPart (1 для многих через INVENTORY_ITEM_ID)
Я пытаюсь выяснить, как написать запрос LINQ, в котором я могу создать анонимный объект, который включает в себя количество ShipSets для каждого CmQueueItem.
var queueItems = from c in dbContext.CmQueueItems
select new
{
InventoryItemID = c.ID,
ShipSets = 0 //[magical LINQ goes here]
};
Он должен сгенерировать оператор SQL, подобный следующему:
select d.inventory_item_id, count(a.shipset_id) as ShipSets
from shipsets a,
instlocs b,
ss_parts c,
cm_queue d
where a.shipset_id = b.shipset_id
and b.instloc_id = c.instloc_id
and c.inventory_item_id = d.inventory_item_id
group by d.inventory_item_id;
Я новичок в LINQ и с трудом понимаю, как выполнять агрегаты и группировки, подобные этой. Есть идеи?
Ответ, приведенный ниже, заключается в использовании ключевого слова let в LINQ:
var query = from c in dbContext.CmQueueItems
let shipSets = (from s in c.ShipSetParts
select s.InstallLocation.ShipSet)
select new
{
InventoryItemId = c.ID,
ShipSets = shipSets.Count(),
};