实体框架嵌套导航属性仅计数

时间:2016-05-06 19:21:42

标签: c# .net entity-framework navigation-properties

我有三个模型类

public class Item1{

    public int Id;

    public List<Item2> Item2List { get; set; }
}

public class Item2{
    public int Id;

    //this is the FK
    public int Item1Id {get;set;}

    public Item1 Item1 {get;set;}

    //Not in db. Ignored field in EntityTypeConfiguration
    public int Item3Count;

    public List<Item3> Item3List { get; set; }
}

public class Item3{
    public int Id;

    //this is the FK
    public int Item2Id {get;set;}

    public Item2 Item2 {get;set;}    
}

我想返回Item1的列表以及关联的Item2列表,并加载与Item 2关联的Item3List的COUNT而不加载Item3List。

这就是我现在正在做的事情:

public IEnumerable<Item1> GetItems()
{
    return base.Query().Include(item1 => item1.Item2List.Select(item2 => item2.Item3List)).ToList();
}

这将返回所有3个对象Item1,Item2和Item3的列表。但我只需要Item3Count中Item3List的计数,而不是整个Item3List列表。我怎样才能做到这一点?我在下面尝试了这个,但它会引发错误。

return base.Query().Include(item1 => item1.Item2List.Select(item2 => new Item2 {
Item3Count = item2.Item3List.Count()
})).ToList();
  

Include路径表达式必须引用导航属性   在类型上定义。使用虚线路径进行参考导航   属性和集合导航的Select运算符   属性。参数名称:路径

2 个答案:

答案 0 :(得分:2)

你想要的是不可能的。当然,您无法在EF LINQ查询中填充未映射的属性,因为这是不映射它的想法。但你已经知道了。

您真正想做的事情是:

context.Item1s.Select(item1 => new Item1
{
    Id = item1.Id,
    Item2s = item1.Item2List.Select(item2 => new Item2List
    {
        Id = item2.Id,
        Item3Count = item2.Item3List.Count()
    })
})

但EF不允许您在EF查询中构造实体对象。

替代方案并不吸引人。

您可以构建匿名类型的结构......

context.Item1s.Select(item1 => new
{
    Item1 = item1,
    Item2s = item1.Item2List.Select(item2 => new
    {
        Item2 = item2,
        Item3Count = item2.Item3List.Count()
    })
})

...并使用它来构建Item1个对象列表,每个对象的Item2ListItem2Item3Count个值Mapper.CreateMap<Item1,Item1Dto>(); Mapper.CreateMap<Item2,Item2Dto>();

更好,但仍然不接近理想的,是使用AutoMapper并将实体映射到DTO:

Item3Count

您可以使用AutoMapper flattening feature填充Item2Dto。为此,Item3ListCount应该有一个属性Item3List.Count(),AutoMapper会将其转换为func getDayOfWeekForFirstDayOfMonthFromDateString(dateString:String) -> String? { let formatter = NSDateFormatter() formatter.dateFormat = "yyyy-MM-dd" if let date = formatter.dateFromString(dateString) { if let firstOfMonth = NSCalendar.currentCalendar().dateFromComponents(NSCalendar.currentCalendar().components([.Year, .Month], fromDate: date)) { formatter.dateFormat = "EEEE" return formatter.stringFromDate(firstOfMonth) } } return nil }

答案 1 :(得分:0)

您没有使用ef约定。请参阅https://msdn.microsoft.com/en-us/data/jj819164.aspx。 你必须做这样的事情:

public class Item1{

  public int Item1Id{get;set;}

  public ICollection<Item2> Item2s{ get; set; }
}

public class Item2{

  public int Item2Id{get;set;}

  //Not in db. Ignored field in mapping
  [NotMapped]
  public int Item3Count => Item3s.Count;

  //this is the FK
  public int Item1Id{get;set;}

  public Item1 Item1 {get;set;}

  public ICollection<Item3> Item3s{ get; set; }
}

public class Item3{
  public int Item3Id;

  //FK
  public int Item2Id {get;set;}

  public Item2 Item2 {get;set;}

}

现在:

public IEnumerable<int> GetCounts()
{
   //get the items1 including its List of item2
   var items1 = base.Query().Include(item1 => item1.Item2s);

   //get the counts
   var counts = items1.Select(item1 => item1.Item2s.Select(item2 => item2.Item3Count));

   //now in counts you have what you want, do what you please with it
   //and return it
   return counts;

}

我没有尝试过,因为它适合你。