假设我有一个这样的模型:
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}\" }}" );
}
}
结果:
数据库中的表:
关于c# - 从 EF 核心获取实体而不加载所有字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52407036/