【问题标题】:Include only partial entity in EF6 Include在 EF6 中仅包含部分实体
【发布时间】:2023-03-13 09:08:01
【问题描述】:

我有一个模型,其中包括可以具有具有 Id、Name 和 BinaryData 属性的附件的 Punches。

如果我这样做:

var result = context.PunchSet
   .Where(p => p.PunchType == punchType && p.Project.Id == projectId)
   .Include(c => c.Contractor)
   .Include(c => c.ClearedBy)
   .Include(c => c.CreatedBy)
   .Include(a => a.Attachments)

查询很慢,因为附件可能很多而且很大。在这种情况下,我只需要附件的 ID 和名称。所以我尝试了:

var result = context.PunchSet
    .Where(p => p.PunchType == punchType && p.Project.Id == projectId)
    .Include(c => c.Contractor)
    .Include(c => c.ClearedBy)
    .Include(c => c.CreatedBy)
    .Include(a => a.Attachments.Select(a2 => new Attachment() { Id=a2.Id, Name=a2.Name} );

但最终会出现这个错误:

包含路径表达式必须引用导航属性 在类型上定义。使用虚线路径进行参考导航 属性和用于集合导航的 Select 运算符 特性。参数名称:路径

不知道这意味着什么,我已经被困了好几个小时了。如何在结果中包含部分实体? IE。不要读取二进制数据。

【问题讨论】:

  • 您不能部分包含。但是,如果您只想阅读而不是更新,则可以省略包含中的附件并单独加载它们。
  • 如何在同一个查询中做到这一点?我不想加载 500 拳,然后必须循环通过它们来获取任何附件(如果有的话)。这将是一个 5 分钟的好旧 SQL 工作。有时这 EF6 的东西会影响到我。
  • 如果您需要加载部分相关的实体,您需要使用匿名类型或 DTO 投影查询。作为例外说明,您只能在 Include 扩展方法中引用导航属性

标签: c# linq entity-framework-6


【解决方案1】:

您可以尝试在单个查询中选择所有需要的属性,然后将它们连接到内存中。

db.PunchSet
    .Include(x => x.Contractor)
    // ... other includes of complete objects
    // then select properties for partial include
    .Select(x => new { obj = x, att = x.Attachments.Select(a => new { a.Id, a.Name }) })
    // end of database query context
    .AsEnumerable()
    // join the results in memory
    .Select(x =>
    {
        x.obj.Attachments = x.att.Select(a => new Attachment() { Id = a.Id, Name = a.Name }).ToList();
        return x.obj;
    });

【讨论】:

    【解决方案2】:

    你可以试试如下图。

    var result =  from p in context.PunchSet 
                   where (p.PunchType == punchType && p.Project.Id == projectId) 
                   select new { 
                               p,  
                               Contractor=p.Contractor,
                               ClearedBy =p.ClearedBy,
                               CreatedBy=p.CreatedBy,
    
                               Attachments= from a in p.Attachments
                                            select new {
                                                         Id=  a.Id,
                                                         Name =a.Name, 
                                                       },
    
                 };
    
    var result2 = result.AsEnumerable() 
                        .Select(c => c.p);
    

    之后,您可以根据需要进行迭代:)

    foreach(var r in result2 ) 
    { 
        foreach(var a in r.Attachments) 
         {
           //your code; 
         }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      相关资源
      最近更新 更多