如何在Entity Framework Core 6 - C#中延迟(懒加载)加载二进制属性byte[]?

6

我有一个简单的表,其中包含键、名称和二进制内容。 我需要仅在需要时加载二进制内容。 在Linq2Sql中这非常简单,但在EF Core 6中,除了导航集合的惰性加载之外,我找不到任何东西,而这并不是我所需要的。 我是否遗漏了什么或者EF Core确实缺失此功能? Jiri

public class Content {
 public int Id { get; set; }
 public string Name { get; set; }
 public byte[] Data { get; set; } // How to delay loading this ? 
}

命令

ctx.Content.Select(x =x.Id==1);

期望的SQL如下:

SELECT Id, Name FROM Content WHERE Id=1

1
https://learn.microsoft.com/en-us/ef/core/modeling/table-splitting - Gert Arnold
好的,我有一个代码库正在从Linq2Sql迁移到EFc6,大约有3000个linq查询 - 不想全部重写。我只是惊讶于在EFc经过6次迭代后,像属性延迟加载这样简单的东西竟然缺失了... - Jiří Zídek
1
我认为你可能误解了之前提到的表拆分。更确切地说,你有两个不同的C#实体共享数据库中相同未更改的表格。 "轻量级"实体使用一些列集X,而"完整"实体使用一些列集Y。 - Caius Jard
正如Syvatoslav所提到的,您也可以仅选择表中的一部分列进行常规使用,并在更有限的需求上加载不同的集合(包括大型列),当您需要JSON数据时。 - Caius Jard
很遗憾,投影会阻止更新(即使是在读取场景下也需要大量重写)。 - Jiří Zídek
显示剩余7条评论
1个回答

7
唯一可选载入某些内容的方法是使用导航属性。
在您的情况下,解决方案是创建一个虚拟实体,其中只包含 byte[] 属性,并使用表拆分(Table Splitting) 配置它与主实体共享相同的表。
请注意,这只是逻辑上的分离,不需要更改数据库架构。表拆分文档的第一行就指出:

EF Core 允许将两个或多个实体映射到单个行。这被称为 表拆分表共享

您可能会对术语“拆分”感到困惑。它并没有将数据库中的物理表拆分,而是将其(共享)分割成几个实体。
例如: 模型
public class Content
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ContentData Data { get; set; }
}

public class ContentData
{
    public byte[] Data { get; set; }
}

配置

modelBuilder.Entity<ContentData>()
    .ToTable("Content"); // must be the same as for Content entity
modelBuilder.Entity<ContentData>()
    .Property<int>("ContentId");
modelBuilder.Entity<ContentData>()
    .HasKey("ContentId");

modelBuilder.Entity<Content>()
    .HasOne(e => e.ContentData)
    .WithOne()
    .HasForeignKey<ContentData>("ContentId");

现在Content.Data不会自动加载,您可以在需要时使用常规的Include来加载它。唯一的缺点是多了一个对象实例和实际的byte[]属性访问器-content.Data.Data而不是原始的content.Data


只要内容不是一个拥有的实体,这个方法就有效。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接