了解NPGSQL和实体框架中一对多关系的行为

问题描述 投票:0回答:1

我有两个PostgreSQL表“ stock_appreciation_rights”和“ sar_vest_schedule”,它们映射到类“ StockAppreciationRights”和“ SarVestingUnit”。关系是这样的:一个SarVestingUnit与一个StockAppreciationRights相关联,而一个StockAppreciationRight与许多SarVestingUnit相关联。这是SarVestingUnit类:

public class SarVestingUnit
{
    public string UbsId { get; set; }
    public short Units { get; set; }
    public DateTime VestDate { get; set; }
    public virtual StockAppreciationRights Sar { get; set; }
}

这里是StockAppreciationRights类:

public class StockAppreciationRights
{
    public StockAppreciationRights()
    {
        SarVestingUnits = new HashSet<SarVestingUnit>();
    }

    public string UbsId { get; set; }
    public DateTime GrantDate { get; set; }
    public DateTime ExpirationDate { get; set; }
    public short UnitsGranted { get; set; }
    public decimal GrantPrice { get; set; }
    public short UnitsExercised { get; set; }
    public virtual ICollection<SarVestingUnit> SarVestingUnits { get; set; }
}

以及我的dbContext中的摘录:

modelBuilder.Entity<SarVestingUnit>(entity =>
{
    entity.HasKey(e => new { e.UbsId, e.VestDate })
        .HasName("sar_vest_schedule_pkey");

    entity.ToTable("sar_vest_schedule");

    entity.Property(e => e.UbsId)
        .HasColumnName("ubs_id")
        .HasColumnType("character varying");

    entity.Property(e => e.VestDate)
        .HasColumnName("vest_date")
        .HasColumnType("date");

    entity.Property(e => e.Units).HasColumnName("units");

    entity.HasOne(d => d.Sar)
        .WithMany(p => p.SarVestingUnits)
        .HasForeignKey(d => d.UbsId)
        .OnDelete(DeleteBehavior.ClientSetNull)
        .HasConstraintName("sar_vest_schedule_ubs_id_fkey")
        .IsRequired();
});

这是我不了解的行为。如果我像这样从我的dbcontext中获得StockAppreciationRights:

var x = new personalfinanceContext();
//var test = x.SarVestingUnit.ToList();
var pgSARS = x.StockAppreciationRights.ToList();

SarVestingUnits集合在我的StockAppreciationRights对象中为空。同样,如果我只是得到SarVestingUnits而不是像这样的StockAppreciationRights:

var x = new personalfinanceContext();
var test = x.SarVestingUnit.ToList();
//var pgSARS = x.StockAppreciationRights.ToList();

我的SarVestingUnit对象中的Sar属性为null。但是,如果我两个都这样的话:

var x = new personalfinanceContext();
var test = x.SarVestingUnit.ToList();
var pgSARS = x.StockAppreciationRights.ToList();

然后,所有内容均应填充。有人可以解释这种行为吗?显然,我是实体框架和PostgreSQL的新手。

c# postgresql entity-framework npgsql
1个回答
0
投票

根据您描述的行为,懒惰加载似乎已禁用或不可用(即EF Core <= 2.1)

延迟加载将为尚未加载的相关引用分配代理,以便以后访问这些引用时,将对DbContext进行数据库查询以检索它们。这样可以“按需”检索数据,但是会导致严重的性能损失。

或者,您可以渴望加载相关数据。例如:

var pgSARS = context.StockAppreciationRights.Include(x => x.SarVestingUnits).ToList();

将告诉EF加载StockAppreciation权利,并为每个条目预取任何归属单位。您可以使用IncludeThenInclude向下钻取并预取任意数量的依赖项。

您的最后一个示例似乎起作用的原因是,EF将自动填充上下文所知道的关系。当您加载第一个集合时,它不会解析任何相关实体,但是,加载第二个集合并且EF已经知道相关的其他实体,并将为您自动设置这些引用。

尽管EF的真正功能不是处理实体到表的一对一映射(在编辑/插入之外),而是利用投影来提取关系数据来填充所需的内容。利用Select或Automapper的ProjectTo方法意味着您可以通过映射的EF关系提取所需的任何数据,并且EF可以为您构建一个高效的查询来获取它,而不必担心延迟或急于加载。例如,如果您想获得归属单位及其相关权利详细信息的列表:

var sars = context.StockAppreciationRights.Select(x => new SARSummary
{
    UbsId = x.UbsId,
    Units = x.Units,
    VestDate = x.VestDate,
    GrantDate = x.Sar.GrantDate,
    ExpirationDate = x.Sar.ExpirationDate,
    UnitsGranted = x.Sar.UnitsGranted,
    GrantPrice = x.Sar.GrantPrice
}).ToList();

Select语句中,您可以访问任何相关详细信息以平化为可满足您的即时需求的视图模型,甚至可以组成简化的视图模型层次结构来满足视图/消费者的需求。

© www.soinside.com 2019 - 2024. All rights reserved.