总结多层次关系

时间:2014-02-07 01:59:02

标签: linq entity-framework

首先使用EF代码,我有以下4个实体

public class Item {
  public int Id { get; set; }
  public string Name { get; set; }
}

public class Location {
  public int Id { get; set; }
  public string Name { get; set; }
}

public class InventoryAdjustment {
  public int Id { get; set; }
  public virtual Location Location { get; set; }
  public virtual ICollection<AdjustmentLine> Lines { get; set; }
}

public class AdjustmentLine {
  public int Id { get; set; }
  public virtual Item Item { get; set; }
  public int Quantity { get; set; }
}

我要做的是使用最少的数据库往返来获取每个位置的每个项目的所有库存调整的总和。

到目前为止我取得的最好成绩是:

using (var db = new InventoryContext()) {
  var items = db.Items.ToList();
  var locations = db.Locations.ToList();

  foreach (var item in items) {
    Console.WriteLine(item.Name+":");
    foreach (var location in locations) {
      Console.Write("\t" + location.Name + ": ");
      var qty = db.InventoryAdjustments
          .Where(p => p.Location.Id == location.Id)
          .SelectMany(p => p.Lines)
          .Where(p => p.Item.Id == item.Id)
          .Select(p => (int?)p.Quantity)
          .Sum();
      Console.WriteLine(qty ?? 0);
    }
  }  
  Console.Read();
}

以上输出:

Item1:
    Location1: 2
    Location2: 12
    Location3: 21
Item2:
    Location1: 4
    Location2: 0
    Location3: 0
Item3:
    Location1: 1
    Location2: 17
    Location3: 0

但是在数据库中有3个项目和3个位置,上面的代码会导致11次调用数据库。 2用于获取物品和位置,9用于计算数量总和。

有没有更好的方法来获得最少的往返次数?

1 个答案:

答案 0 :(得分:0)

这应该可行:

using (var db = new InventoryContext())
{
    var items = db.Items.ToList();
    var locations = db.Locations.ToList();

    items
        .Select(item =>
        {
            Console.WriteLine(item.Name + ":");
            return item;
        })
        .SelectMany(item => locations.Select(location => new { item, location }))
        .GroupJoin(
            db.InventoryAdjustments
                .SelectMany(
                    inventoryAdjustment => inventoryAdjustment.Lines.Select(
                        adjustmentLine => new { key = new { locationId = inventoryAdjustment.Location.Id, itemId = adjustmentLine.Item.Id }, adjustmentLine.Quantity }
                    )
                ),
            x => new { locationId = x.location.Id, itemId = x.item.Id },
            y => y.key,
            (x, y) =>
            {
                Console.WriteLine("\t {0}: {1}", x.location.Name, y.Sum(a => a.Quantity));
                return 0;
            }
        ).ToList();
    Console.Write("\nPress any key...");
    Console.ReadKey();
}