简体   繁体   中英

Get an entity from EF core without loading all fields

Let's say I have a model like this:

public class Model {
    [Key]
    public int Id { get; set; }
    public string SmallData { get; set; }
    public byte[] VeryLargeBlob { get; set; }
}

I need to read an entity from the database and use only the field SmallData , and the VeryLargeBlob is not needed. VeryLargeBlob is very large (say, several megabytes) and reading it from database can affect performance.

I understand that I can choose some of the fields in this way:

var data = context.Model.Where(m => m.Id == Id).Select(m => new { Id = m.Id, SmallData = m.SmallData }).FirstOrDefault();

But I need a Model instance and not an anonymous object, so that I can use it for later queries. Even if I hack it and make it return a Model object the instance isn't tracked and won't be compatible with lazy loading.

Is there a way to load only partial data from the model?

Use "Table Splitting" to split a single table among two or more entity classes, allowing you to control if and when you load certain properties. One achieves this by specifying the same table name for multiple entities and using a shared primary key (PK of dependent entities are a FK to the principal entity). Here's an example:

public class PrincipalEntity
{
    [Key]
    public int Id { get; set; }
    public string PrincipalProperty { get; set; }
    public virtual DependentEntity Dependent { get; set; }
}

public class DependentEntity
{
    [Key]
    public int Id { get; set; }
    public string DependentProperty { get; set; }
}

public class PricipalEntityConfiguration : IEntityTypeConfiguration<PrincipalEntity>
{
    public void Configure( EntityTypeBuilder<PrincipalEntity> builder )
    {
        //builder.HasKey( pe => pe.Id );
        builder.HasOne( pe => pe.Dependent )
            .WithOne()
            .HasForeignKey<DependentEntity>( de => de.Id ); // FK is PK
        builder.ToTable( "YourTableName" );
    }
}

public class DependentEntityConfiguration : IEntityTypeConfiguration<DependentEntity>
{
    public void Configure( EntityTypeBuilder<DependentEntity> builder )
    {
        //builder.HasKey( de => de.Id );
        builder.ToTable( "YourTableName" ); // same table name
    }
}

public class TestContext : DbContext
{
    public DbSet<PrincipalEntity> PrincipalEntities { get; set; }
    public DbSet<DependentEntity> DependentEntities { get; set; }

    public TestContext( DbContextOptions options ) : base( options )
    {
    }

    protected override void OnModelCreating( ModelBuilder modelBuilder )
    {
        modelBuilder.ApplyConfiguration( new PricipalEntityConfiguration() );
        modelBuilder.ApplyConfiguration( new DependentEntityConfiguration() );
    }
}

class Program
{
    static void Main( string[] args )
    {
        var options = new DbContextOptionsBuilder<TestContext>()
            .UseSqlServer( "Server=(localdb)\\mssqllocaldb;Database=EFCoreTest;Trusted_Connection=True;" )
            .Options;

        using( var dbContext = new TestContext( options ) )
        {
            var pEntity = new PrincipalEntity()
            {
                PrincipalProperty = "Principal Property Value",
                Dependent = new DependentEntity()
                {
                    DependentProperty = "Dependent Property Value",
                },
            };

            dbContext.PrincipalEntities.Add( pEntity );
            dbContext.SaveChanges();
        }

        using( var dbContext = new TestContext( options ) )
        {
            var pEntity = dbContext.PrincipalEntities
                // eager load dependent
                .Include( pe => pe.Dependent )
                .Single();

            System.Console.WriteLine( "Loaded Principal w/ Dependent Eager-Loaded:" );
            DisplayValues( pEntity );

            dbContext.Entry( pEntity.Dependent ).State = EntityState.Detached;
            dbContext.Entry( pEntity ).State = EntityState.Detached;
            pEntity = dbContext.PrincipalEntities.Single();

            System.Console.WriteLine();
            System.Console.WriteLine( "Load Principal Entity Only:" );
            DisplayValues( pEntity );

            // explicitly load dependent
            dbContext.Entry( pEntity )
                .Reference( pe => pe.Dependent )
                .Load();

            System.Console.WriteLine();
            System.Console.WriteLine( "After Explicitly Loading Dependent:" );
            DisplayValues( pEntity );                
        }
    }

    private static void DisplayValues( PrincipalEntity pe )
    {
        System.Console.WriteLine( $"Principal Entity = {{ Id: {pe.Id}, PrincipalProperty: \"{pe.PrincipalProperty}\" }}" );

        if( null == pe.Dependent )
        {
            System.Console.WriteLine( "Principal Entity's Dependent property is null" );
        }
        else
        {
            System.Console.WriteLine( $"Dependent Entity = {{ Id: {pe.Dependent.Id}, DependentProperty: \"{pe.Dependent.DependentProperty}\" }}" );
        }
    }

Results:

在此处输入图片说明

Table in Database:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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