Entity framework 如何排除a";中的列;然后包括;实体框架中的对象选择查询

Entity framework 如何排除a";中的列;然后包括;实体框架中的对象选择查询,entity-framework,select,Entity Framework,Select,我正在执行一个复杂的实体框架select查询,我想排除“ThenInclude”对象中的一个特定列 我试图在StackOverflow中找到一个解决方案,但没有人真正适合我的复杂查询 以下是查询: // topLevelId is given when we get here await this.Context.TopLevel .Include(c1 => c1.Child1) .Include(c2 => c2.C

我正在执行一个复杂的实体框架select查询,我想排除“ThenInclude”对象中的一个特定列

我试图在StackOverflow中找到一个解决方案,但没有人真正适合我的复杂查询

以下是查询:

// topLevelId is given when we get here
await this.Context.TopLevel
                .Include(c1 => c1.Child1)
                .Include(c2 => c2.Child2)
                .Include(c3 => c3.Child3)
                .Include(c4 => c4.Child4).ThenInclude(gc1 => gc1.GrandChild1)
                .Include(c4 => c4.Child4).ThenInclude(gc2 => gc2.GrandChild2)
                .Include(c4 => c4.Child4).ThenInclude(gc3 => gc3.GrandChild3)
                .FirstAsync(tl => tl.TopLevelId == topLevelId);
我需要从中排除列的“ThenIncluded”对象是1,它属于以下类型:

public partial class Document
{
    public Document()
    {
        this.MyType = new HashSet<MyType>();
    }

    public Guid DocumentId { get; set; }
    public string DocumentName { get; set; }
    public string FileName { get; set; }
    public string MimeType { get; set; }
    public byte[] Data { get; set; }

    public ICollection<MyType> MyType { get; set; }
}
公共部分类文档
{
公共文件()
{
this.MyType=new HashSet();
}
公共Guid DocumentId{get;set;}
公共字符串DocumentName{get;set;}
公共字符串文件名{get;set;}
公共字符串MimeType{get;set;}
公共字节[]数据{get;set;}
公共ICollection MyType{get;set;}
}
我要排除的列是Data(字节数组)


注意:我在其他查询和更新中需要该列,因此我不能忽略EF模型中的该列。

根据您的消费者需要,您可以使用
.Select()
告诉EF您要提取哪些数据。这可以像数据模型一样是关系型的,也可以将层次结构中的数据扁平化为更简单的结构

例如,假设:

await this.Context.TopLevel
                .Include(c1 => c1.Child1).ThenInclude(gc1 => gc1.GrandChild1)
                .FirstAsync(tl => tl.TopLevelId == topLevelId); 
假设1是具有字节数组的文档

public class TopLevelViewModel
{
   public int TopLevelId { get; set; }
   public int Child1Id { get; set; }
   public string DocumentName { get; set; }
   public string FileName { get; set; }
}

await this.Context.TopLevel
    .Select(x => new TopLevelViewModel
    {
        TopLevelId = x.TopLevelId,
        Child1Id = x.Child1.Child1Id,
        DocumentName = x.Child1.Grandchild1.DocumentName,
        FileName = x.Child1.GrandChild1.FileName
    }).SingleAsync(x => x.TopLevelId = topLevelId);
如果子项表示一对多集合,则可以使用其相关文档详细信息定义ChildViewModel:

public class TopLevelViewModel
{
   public int TopLevelId { get; set; }
   public ICollection<Child1ViewModel> Children { get; set; } = new List<Child1ViewModel>();
}
public class Child1ViewModel
{
   public int Child1Id { get; set; }
   public string DocumentName { get; set; }
   public string FileName { get; set; }
}

await this.Context.TopLevel
    .Select(x => new TopLevelViewModel
    {
        TopLevelId = x.TopLevelId,
        Children = x.Child1s.Select( c => new Child1ViewModel
        {
            Child1Id = c.Child1Id,
            DocumentName = c.Grandchild1.DocumentName,
            FileName = c.GrandChild1.FileName
        }).ToList()
    }).SingleAsync(x => x.TopLevelId = topLevelId);
公共类TopLevelViewModel
{
公共int TopLevelId{get;set;}
公共ICollection子项{get;set;}=new List();
}
公共类Child1ViewModel
{
public int Child1Id{get;set;}
公共字符串DocumentName{get;set;}
公共字符串文件名{get;set;}
}
等待this.Context.TopLevel
.选择(x=>new TopLevelViewModel
{
TopLevelId=x.TopLevelId,
Children=x.Child1s.选择(c=>newchild1viewmodel
{
Child1Id=c.Child1Id,
DocumentName=c.1.DocumentName,
FileName=c.1.FileName
})托利斯先生()
}).SingleAsync(x=>x.TopLevelId=TopLevelId);

您可以构建关系和数据,以便根据需要进行回退。其优点是,您只需收回所需的数据字段,这些字段可以减少有效负载大小以提高性能,利用数据库上的索引,并避免向使用者透露太多有关数据结构的信息。

您必须这样做。选择()所需的其他属性,没有特定的排除方法谢谢您的快速回复,但是我如何在包含对象中做到这一点?我在简单的示例中看到了Select(),但是Include/thenclude中没有任何内容……您不能在Include中执行此操作,以后您必须在导航属性中执行此操作感谢您的持续帮助。之后的选择会是什么样子?看。谢谢你的全面回答!因此,Select不需要Include/thenclude?还有:如果我需要完整的其他孩子怎么办(我只需要“减少”孙子1)。是的,/w选择“你不需要包括”。关于完整的其他记录,这实际上取决于你使用它们的目的。如果是内部代码逻辑,则可以使用Select按原样选择实体。但是,如果要传递到DbContext范围之外,例如返回到视图,那么我建议组合视图模型。Automapper可以通过
ProjectTo
代替
Select
帮助将实体转换为查询中的视图模型。对于返回数据,选择的越少,整体性能越好。EF是否认识到Automapper只需要返回实体的某些属性来转换为viewmodel,并将其他列投影到别处?ProjectTo将根据映射设置转换DTO/viewmodel中请求的字段。它与EF的
IQueryable
行为一起工作,因此如果视图模型只有一些字段,它将有效地为您仅为这些字段构建Select语句。在使用Select和ProjectTo时,我建议使用像ExpressProfiler这样的探查器来监听数据库并捕获生成的SQL,以验证您的查询是否只提取预期的字段。它还有助于检测性能问题,如意外的延迟加载。@StevePy:谢谢,我将在周一试用。