简体   繁体   English

使用 Ef Core 选择分层数据中的特定列

[英]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.

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