EF Core First 预加载继承筛选器
EF Core First Eager Loading Inheritance Filter
我定义了以下实体:
public class Computer
{
[Key]
public int Id { get; set; }
[Required]
[StringLength(15)]
public string Name { get; set; } = null!;
[Required]
public List<ComputerAction> Actions { get; set; } = new();
}
public abstract class ComputerAction
{
[Key]
public int Id { get; set; }
public List<HistoryEntry> History { get; set; } = new();
public Computer Computer { get; set; } = null!;
[NotMapped]
public Status Status => History.LastOrDefault()?.Status ?? Status.Unknown;
public abstract Task<HistoryEntry> ExecuteAsync();
}
public class RenewCertificateAction : ComputerAction
{
public override Task<HistoryEntry> ExecuteAsync()
{
// Whatever
}
}
public class PingAction : ComputerAction
{
private readonly Ping _ping = new();
public override async Task<HistoryEntry> ExecuteAsync()
{
// Whatever
}
}
public class HistoryEntry
{
[Key]
public int Id { get; set; }
[Required]
public Status Status { get; set; }
[Required]
public DateTime WhenExecuted { get; set; }
}
而我的 DbContext 如下:
public class ComputerContext : DbContext
{
public ComputerContext(DbContextOptions<ComputerContext> options)
: base(options)
{
}
public static readonly string ComputerDb = nameof(ComputerDb);
public DbSet<Computer> Computers { get; set; } = null!;
public DbSet<RenewCertificateAction> RenewCertificateActions { get; set; } = null!;
public DbSet<PingAction> PingActions { get; set; } = null!;
public DbSet<HistoryEntry> History { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Computer>().HasMany(x => x.Actions).WithOne(x => x.Computer).OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<ComputerAction>().ToTable("ComputerActions").HasMany(x => x.History).WithOne().OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<HistoryEntry>().ToTable("ComputerActionEntries");
}
}
我想获取所有计算机的列表,但如果它们碰巧有类型为 PingAction
的操作,则也加载该操作(并且仅加载该操作,而不是所有操作)。
对我来说合乎逻辑的是 dbContext.Computers.Include(x => x.Actions.OfType<PingAction>())
之类的东西,但显然不能将其转换为查询。我怎样才能只对特定类型的 Actions
执行 Include
?
你可以使用where里面的include:
dbContext.Computers.Include(x => x.Actions.Where(action => action is PingAction))
更多解释::
我定义了以下实体:
public class Computer
{
[Key]
public int Id { get; set; }
[Required]
[StringLength(15)]
public string Name { get; set; } = null!;
[Required]
public List<ComputerAction> Actions { get; set; } = new();
}
public abstract class ComputerAction
{
[Key]
public int Id { get; set; }
public List<HistoryEntry> History { get; set; } = new();
public Computer Computer { get; set; } = null!;
[NotMapped]
public Status Status => History.LastOrDefault()?.Status ?? Status.Unknown;
public abstract Task<HistoryEntry> ExecuteAsync();
}
public class RenewCertificateAction : ComputerAction
{
public override Task<HistoryEntry> ExecuteAsync()
{
// Whatever
}
}
public class PingAction : ComputerAction
{
private readonly Ping _ping = new();
public override async Task<HistoryEntry> ExecuteAsync()
{
// Whatever
}
}
public class HistoryEntry
{
[Key]
public int Id { get; set; }
[Required]
public Status Status { get; set; }
[Required]
public DateTime WhenExecuted { get; set; }
}
而我的 DbContext 如下:
public class ComputerContext : DbContext
{
public ComputerContext(DbContextOptions<ComputerContext> options)
: base(options)
{
}
public static readonly string ComputerDb = nameof(ComputerDb);
public DbSet<Computer> Computers { get; set; } = null!;
public DbSet<RenewCertificateAction> RenewCertificateActions { get; set; } = null!;
public DbSet<PingAction> PingActions { get; set; } = null!;
public DbSet<HistoryEntry> History { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Computer>().HasMany(x => x.Actions).WithOne(x => x.Computer).OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<ComputerAction>().ToTable("ComputerActions").HasMany(x => x.History).WithOne().OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<HistoryEntry>().ToTable("ComputerActionEntries");
}
}
我想获取所有计算机的列表,但如果它们碰巧有类型为 PingAction
的操作,则也加载该操作(并且仅加载该操作,而不是所有操作)。
对我来说合乎逻辑的是 dbContext.Computers.Include(x => x.Actions.OfType<PingAction>())
之类的东西,但显然不能将其转换为查询。我怎样才能只对特定类型的 Actions
执行 Include
?
你可以使用where里面的include:
dbContext.Computers.Include(x => x.Actions.Where(action => action is PingAction))
更多解释::