简体   繁体   English

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

[英]Entity Framework nested navigation properties count only

I have three model classes 我有三个模型类

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;}    
}

I want to return the list of Item1 along with list of associated Item2, and load the COUNT of Item3List associated with Item 2 without loading the Item3List. 我想返回Item1的列表以及相关Item2的列表,并加载与Item2相关联的Item3List的COUNT而不加载Item3List。

Here is what I am doing right now: 这就是我现在正在做的事情:

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

This returns me the list of all 3 objects Item1, Item2 and Item3. 这将返回所有3个对象Item1,Item2和Item3的列表。 But I only need the count of Item3List in Item3Count, and not the entire Item3List list. 但我只需要Item3Count中Item3List的计数,而不是整个Item3List列表。 How can I achieve that? 我怎样才能做到这一点? I tried this below, but it throws error. 我在下面尝试过这个,但它会抛出错误。

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

The Include path expression must refer to a navigation property defined on the type. Include路径表达式必须引用在类型上定义的导航属性。 Use dotted paths for reference navigation properties and the Select operator for collection navigation properties. 使用虚线路径作为参考导航属性,使用Select运算符作为集合导航属性。 Parameter name: path 参数名称:路径

What you want is not possible. 你想要的是不可能的。 Of course you can't populate a not-mapped property in an EF LINQ query, because that's the idea of not mapping it. 当然,您无法在EF LINQ查询中填充未映射的属性,因为这是不映射它的想法。 But you already knew that. 但你已经知道了。

What you'd really like to do is something like this: 你真正想做的是这样的事情:

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

But EF doesn't allow you to construct an entity object in an EF query. 但EF不允许您在EF查询中构造实体对象。

The alternatives are not appealing. 替代方案并不吸引人。

You could build a structure of anonymous types ... 你可以建立一个匿名类型的结构......

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

... and use this to construct a list of Item1 objects, each having their Item2List s of Item2 s with Item3Count values. ...并使用它来构造Item1对象的列表,每个对象的Item2List都是Item2的,具有Item3Count值。

Better, but still not close to what would be ideal, is to use AutoMapper and map the entities to DTOs: 更好,但仍然不接近理想的是使用AutoMapper并将实体映射到DTO:

Mapper.CreateMap<Item1,Item1Dto>();
Mapper.CreateMap<Item2,Item2Dto>();

You can use AutoMapper's flattening feature to populate Item3Count . 您可以使用AutoMapper的展平功能填充Item3Count To do this, Item2Dto should have a property Item3ListCount and AutoMapper will translate this to Item3List.Count() . 为此, Item2Dto应具有属性Item3ListCount ,AutoMapper将其转换为Item3List.Count()

You are not using the ef conventions. 您没有使用ef约定。 Refer to https://msdn.microsoft.com/en-us/data/jj819164.aspx for that. 请参阅https://msdn.microsoft.com/en-us/data/jj819164.aspx You have to do something like this: 你必须做这样的事情:


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;}

}

Now: 现在:

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;

} }


I haven't tried this by it should works for you. 我没有试过这个应该适合你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM