简体   繁体   English

实体框架:跳过几列或从相关实体中选择为空

[英]Entity Framework: Skip few columns or select as null from related entities

I have three entities as below 我有三个实体如下

public partial class Ticket
{
    public int TicketId { get; set; }
    ...
    public virtual ICollection<TicketComment> TicketComments { get; set; }
}

public partial class TicketComment
{
    public int CommentId { get; set; }
    public int TicketId { get; set; }
    ...
    public virtual ICollection<CommentAttachment> CommentAttachments { get; set; }
    public virtual Ticket Ticket { get; set; }
}

public partial class CommentAttachment
{
    public int FileId { get; set; }
    public int CommentID { get; set; }
    public string FileName { get; set; }
    public int FileSize { get; set; }
    public byte[] FileContents { get; set; }  // holds large data

    public virtual TicketComment TicketComment { get; set; }
}

Here each Ticket can have multiple comments and each Comment can have 1 or 0 attachment. 这里每张票可以有多个注释,每个注释可以有1或0个附件。 I am trying to eager load all related entities for a given ticket with following code 我试图用以下代码急切加载给定票证的所有相关实体

var query = context.Tickets.Where(t => t.TicketId == ticketid)
             .Include(t => t.TicketComments.Select(c => c.CommentAttachments));

It is doing the job correctly. 它正确地完成了工作。

Only the problem is that, it is also loading byte[] FileContents , which often has quite large data. 唯一的问题是,它还加载了byte[] FileContents ,它通常具有相当大的数据。 I want to avoid it. 我想避免它。

Is there any way i can select NULL for FileContents or skip this column at all? 有什么办法我可以为FileContents选择NULL或者完全跳过这一列?

I had tried with following 我试过跟随

var query = context.Tickets.Where(t => t.TicketId == ticketid)
            .Include(t => t.TicketComments
                .Select(c => c.CommentAttachments
                    .Select(ca => new CommentAttachment()
                    {
                        CommentID = ca.CommentID,
                        FileContents = null,
                        FileId = ca.FileId,
                        FileName = ca.FileName,
                        FileSize = ca.FileSize
                    })));

But it is giving error 但它给出了错误

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

Any ideas to avoid loading FileContents column ? 有什么想法可以避免加载FileContents列?

public partial class CommentAttachment
{
    public int FileId { get; set; }
    public int CommentID { get; set; }
    public string FileName { get; set; }
    public int FileSize { get; set; }

    public virtual TicketComment TicketComment { get; set; }
}

public class FileContent
{
     FileContentId {get;set;}
     public int FileId { get; set; } // HERE IS THE FORGEIN KEY YOU HAVE TO UPDATE IT manually
     public byte[] FileContents { get; set; }  // holds large data
}

In this way you can load the FileContent only by need you have the CommentAttachment Id and you can include it any time. 通过这种方式,您只需要拥有CommentAttachment Id即可加载FileContent,并且您可以随时包含它。

Returning a null getter but allowing setter to function in EF 6.0 and OData v4. 返回null getter但允许setter在EF 6.0和OData v4中运行。

I've come across this same issue. 我遇到过同样的问题。 The accepted answer is definitely a workable option and I almost implemented it today, but I was hoping to perform the task in code. 接受的答案肯定是一个可行的选择,我今天几乎实现了它,但我希望在代码中执行任务。 My model differs slightly than what you have available in that a byte[] Timestamp column is available. 我的模型略有不同,因为byte[] Timestamp列可用。 Posting this workaround in the event that it can assist someone later. 如果以后可以帮助某人,则发布此解决方法。

For my case, the byte[] FileContents serves as a backup to a directory repository where we use the database to rebuild the directory structure and file contents if the front-end is wiped out for various reasons. 对于我的情况, byte[] FileContents用作目录存储库的备份,如果前端因各种原因被清除,我们使用数据库来重建目录结构和文件内容。 So essentially we only POST/SET FileContents, we never read it through the front end program. 基本上我们只有POST / SET FileContents,我们从未通过前端程序读取它。

public partial class CommentAttachment
{
     //required for overriding get/set auto-property
     private byte[] _FileContents; 

     public int FileId { get; set; }
     public int CommentID { get; set; }
     public string FileName { get; set; }
     public int FileSize { get; set; }
     public byte[] FileContents 
     { 
          get
          {
               return Timestamp != null ? null : _FileContents;
          } 
          set
          {
               _FileContents = value;
          }
     }  // holds large data

     public virtual TicketComment TicketComment { get; set; }
     //Concurrency Token - triggered on create or update
     public byte[] Timestamp { get; set; }
 }

The above allowed our database table to stay the same, only the EF POCO changed. 上面允许我们的数据库表保持不变,只有EF POCO改变了。 When creating a CommentAttachment record the Timestamp field is null/doesn't exist because it is triggered by the database; 创建CommentAttachment记录时, Timestamp字段为null /不存在,因为它是由数据库触发的; this allows _FileContents to be populated. 这允许填充_FileContents。 When selecting a record, Timestamp is populated with a value from the database so FileContents is set to null to avoid querying the large data sets. 选择记录时,会使用数据库中的值填充Timestamp ,因此将FileContents设置为null以避免查询大型数据集。

PUT/PATCH/POST works fine with this method when applied to OData v4 as well due to Timestamp not being passed for insert/update as it is a database triggered population. 当应用于OData v4时,PUT / PATCH / POST也可以正常使用此方法,因为它不是为了插入/更新而传递Timestamp ,因为它是数据库触发的填充。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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