[英]Get an entity from EF core without loading all fields
假设我有一个这样的模型:
public class Model {
[Key]
public int Id { get; set; }
public string SmallData { get; set; }
public byte[] VeryLargeBlob { get; set; }
}
我需要从数据库读取一个实体,并且仅使用字段SmallData
,并且VeryLargeBlob
。 VeryLargeBlob
非常大(例如,几兆字节),从数据库中读取它可能会影响性能。
我了解可以通过这种方式选择一些字段:
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}\" }}" );
}
}
结果:
数据库中的表:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.