[英]Select specific columns in hierarchical data with Ef Core
I want to use the functionality of EF Core to automatically map self references to child lists even when I load a flat structure.我想使用 EF Core 的功能自动将自引用映射到子列表,即使我加载了平面结构。 In addition, I want to be able to reduce the number of columns read and transferred.此外,我希望能够减少读取和传输的列数。
My self referencing data structure:我的自引用数据结构:
public class Item
{
public int property1 { get; set; }
/*
Realy long list of columns
*/
public int property30 { get; set; }
public Guid? ParentOid { get; set; }
public virtual Item Parent { get; set; }
public virtual ICollection<OtherObject> OtherObjects { get; set; }
public virtual ICollection<Item> Children { get; set; }
}
I want to achieve loading of the whole hierarchical Tree which can be done easily by using the following query:我想加载整个分层树,这可以通过使用以下查询轻松完成:
(DbContext context) => context.Items.AsQueryable()
And afterwards filtering with:然后过滤:
var rootNodes = items.Where(f => f.ParentOid == null)
This way Ef Core already filled the Children collection on all Children in the tree, this is the behavior that I need!这样 Ef Core 已经填充了树中所有孩子的 Children 集合,这就是我需要的行为!
This query transfers quite huge amounts of data because property1 - property30 are all loaded while I just need a small subset of them.该查询传输了大量数据,因为 property1 - property30 都已加载,而我只需要其中的一小部分。
By using the LINQ select statement with anonymous types, I'm loosing the behavior of building up the tree automatically and I would have to do that by myself.通过使用匿名类型的 LINQ select 语句,我失去了自动构建树的行为,我必须自己完成。
My current solution我目前的解决方案
By setting up another model Item.cs without the properties, I don't need their presence in the select statement of the SQL query.通过设置另一个没有属性的模型 Item.cs,我不需要它们出现在 SQL 查询的 select 语句中。
My problem with this solution is that I need to change the name of Item.cs to eg ItemWithLessProperties.cs and add it to the current context.我对这个解决方案的问题是我需要将 Item.cs 的名称更改为例如 ItemWithLessProperties.cs 并将其添加到当前上下文中。 This would create a conflict in OtherObject.cs because its holding references of Item and not ItemWithLessProperties.这会在 OtherObject.cs 中产生冲突,因为它持有 Item 而不是 ItemWithLessProperties 的引用。 So, I would have to copy this one and add it to the context as well.所以,我必须复制这个并将其添加到上下文中。
By using a total different context for this purpose, I would also have duplicates of the Models Item (which is not a big problem) and OtherObject (which is a problem, because there are multiple of those).通过为此目的使用完全不同的上下文,我还会有 Models Item(这不是大问题)和 OtherObject(这是一个问题,因为它们有多个)的重复项。
Sounds like you need an ItemDTO
.听起来你需要一个ItemDTO
。 You can create an object like您可以创建一个对象,如
public class ItemDTO
{
/*
Properties you need
*/
public int property1 { get; set; }
public int property5 { get; set; }
public int property17 { get; set; }
public int property30 { get; set; }
public virtual ICollection<OtherObject> OtherObjects { get; set; }
public virtual ICollection<Item> Children { get; set; }
}
And also for every nested entity a DTO if you want to also include it in the queryable.如果您还想将其包含在可查询中,那么对于每个嵌套实体也是一个 DTO。
Then you can simply var dtoItems = context.Items.Where(condition).Select(i=>new ItemDTO {/* initialize props */});
然后你可以简单地var dtoItems = context.Items.Where(condition).Select(i=>new ItemDTO {/* initialize props */});
Note : If you are not using a DTO and if the data you pull would be strictly read only and you won't try to update the currently pulled entries in the database it's a good option to also use .AsNoTracking()
to avoid the change tracking overhead of EF Core.注意:如果您没有使用 DTO 并且如果您拉取的数据是严格只读的,并且您不会尝试更新数据库中当前拉取的条目,那么也使用.AsNoTracking()
来避免更改是一个不错的选择跟踪 EF Core 的开销。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.