Entity Framework 嵌套导航属性仅计数
Entity Framework nested navigation properties count only
我有三个型号类
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;}
}
我想要 return Item1 的列表以及关联的 Item2 的列表,并在不加载 Item3List 的情况下加载与 Item2 关联的 Item3List 的 COUNT。
这是我现在正在做的事情:
public IEnumerable<Item1> GetItems()
{
return base.Query().Include(item1 => item1.Item2List.Select(item2 => item2.Item3List)).ToList();
}
这 return 是我的所有 3 个对象 Item1、Item2 和 Item3 的列表。但我只需要 Item3Count 中 Item3List 的计数,而不是整个 Item3List 列表。我怎样才能做到这一点?我在下面试过这个,但它抛出错误。
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. Use dotted paths for reference navigation
properties and the Select operator for collection navigation
properties. Parameter name: path
您没有使用 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;
}
我还没有尝试过,应该适合你。
你想要的是不可能的。当然,您不能在 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
个对象的列表,每个对象都有 Item2List
个 Item2
个具有 Item3Count
个值。
更好但仍不接近理想的是使用 AutoMapper 并将实体映射到 DTO:
Mapper.CreateMap<Item1,Item1Dto>();
Mapper.CreateMap<Item2,Item2Dto>();
您可以使用 AutoMapper 的 flattening feature 来填充 Item3Count
。为此,Item2Dto
应该有一个 属性 Item3ListCount
并且 AutoMapper 会将其转换为 Item3List.Count()
.
我有三个型号类
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;}
}
我想要 return Item1 的列表以及关联的 Item2 的列表,并在不加载 Item3List 的情况下加载与 Item2 关联的 Item3List 的 COUNT。
这是我现在正在做的事情:
public IEnumerable<Item1> GetItems()
{
return base.Query().Include(item1 => item1.Item2List.Select(item2 => item2.Item3List)).ToList();
}
这 return 是我的所有 3 个对象 Item1、Item2 和 Item3 的列表。但我只需要 Item3Count 中 Item3List 的计数,而不是整个 Item3List 列表。我怎样才能做到这一点?我在下面试过这个,但它抛出错误。
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. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties. Parameter name: path
您没有使用 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;
}
我还没有尝试过,应该适合你。
你想要的是不可能的。当然,您不能在 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
个对象的列表,每个对象都有 Item2List
个 Item2
个具有 Item3Count
个值。
更好但仍不接近理想的是使用 AutoMapper 并将实体映射到 DTO:
Mapper.CreateMap<Item1,Item1Dto>();
Mapper.CreateMap<Item2,Item2Dto>();
您可以使用 AutoMapper 的 flattening feature 来填充 Item3Count
。为此,Item2Dto
应该有一个 属性 Item3ListCount
并且 AutoMapper 会将其转换为 Item3List.Count()
.