10

I have simple table with key, name and binary content. I need to load the binary content only when needed. This used to be extra simple in Linq2Sql, but in EF core 6 I cannot find anything except lazy loading of navigation collection, which is not what I need. Am'I missing something or is this missing in 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 ? 
}

Command

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

Expected SQL is:

SELECT Id, Name FROM Content WHERE Id=1
12
  • Can you explain more about why lazy loading is not what you need? Commented Jan 12, 2022 at 17:32
  • Lazy loading does not work on plain properties, only on "navigational one". On trial to use it there is and error: The property 'Content.Data' is being accessed using the 'Reference' or 'Collection' method, but is defined in the model as a non-navigation. Use the 'Property' method to access non-navigation properties Commented Jan 12, 2022 at 17:39
  • 1
    learn.microsoft.com/en-us/ef/core/modeling/table-splitting Commented Jan 12, 2022 at 17:41
  • Navigational properties means property pointing to other table, let say "Alias": public ICollection<Alias> Aliases { get; set; } As seen here: learn.microsoft.com/en-us/ef/core/querying/related-data/… Commented Jan 12, 2022 at 17:42
  • 1
    I think you might have misunderstood the table splitting mentioned earlier. It's more like you have two different c# entities sharing the same unaltered table in the DB. The "lite" entity uses some column set X, the "full fat" entity uses some column set Y. Commented Jan 12, 2022 at 18:32

1 Answer 1

11

The only way to optionally load something is to use navigation property.

The solution in your case is fake entity containing just the byte[] property and configured with table splitting to share the same table with the primary entity.

Note that this is just logical separation and does not require DB schema changes. The very first line in the table splitting documentations states:

EF Core allows to map two or more entities to a single row. This is called table splitting or table sharing.

Probably you are confused with the term splitting. It's not splitting the physical table in the database, but splitting (sharing) it between several entities.

e.g.

Model

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; }
}

Configuration

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");

Now the Content.Data won't be loaded automatically, and you can use the usual Include to load it when needed. The only drawback is one additional object instance and actual byte[] property accessor - content.Data.Data vs the original content.Data.

Sign up to request clarification or add additional context in comments.

1 Comment

This works as long as Content is not an owned entity

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.