c# - 从 EF 核心获取实体而不加载所有字段

标签 c# entity-framework-core

假设我有一个这样的模型:

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

我需要从数据库中读取一个实体并且只使用字段SmallData,并且不需要VeryLargeBlobVeryLargeBlob 非常大(比如几兆字节),从数据库中读取它会影响性能。

我了解可以这样选择部分字段:

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

但我需要一个 Model 实例而不是匿名对象,以便我可以将它用于以后的查询。即使我破解它并让它返回一个 Model 对象,该实例也不会被跟踪并且不会与延迟加载兼容。

有没有办法只从模型中加载部分数据?

最佳答案

使用“表拆分”在两个或多个实体类之间拆分单个表,允许您控制是否以及何时加载某些属性。通过为多个实体指定相同的表名并使用共享主键(依赖实体的 PK 是主体实体的 FK)来实现这一点。这是一个例子:

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

结果:

enter image description here

数据库中的表:

enter image description here

关于c# - 从 EF 核心获取实体而不加载所有字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52407036/

相关文章:

c# - 是否可以通过网络访问Cacti RRD数据库

c# - 乘法时的小数精度

c# - EntityFrameworkCore 映射关系

linux - 在 Linux 服务器中使用 EF 的数据访问库

c# - 是否可以在单独的类中移动层次结构的流畅配置?

c# - root 的 XML 反序列化错误

c# - 打开小型转储 : No native symbols in symbol file

c# - 为什么我的 WinForm 控件在绘制事件之前会闪烁?

entity-framework - EF 核心 : Must be reducible node

c# - Oracle 中使用什么数据类型来存储长字符串?