如何使用外键正确检索数据对象的虚拟属性?

How can I properly retrieve the virtual properties of my Data object with foreign keys?

我正在尝试完成这项工作:

namespace DataService.Domain {

    public class Death {

        [StringLength(10, MinimumLength = 10)]
        public string PersonId { get; set; }

        [StringLength(4, MinimumLength = 4)]
        public string DeathYear { get; set; }


        [NotMapped]
        public virtual Person Person { get; set; }
    }
}

namespace DataService.Domain {

    public class Work {

        [StringLength(10, MinimumLength = 10)]
        public string TitleId { get; set; }

        [StringLength(10, MinimumLength = 10)]
        public string PersonId { get; set; }

        [StringLength(100, MinimumLength = 1)]
        public string Job { get; set; }


        [NotMapped]
        public virtual Title Title { get; set; }

        [NotMapped]
        public virtual Person Person { get; set; }
    }
}
namespace DataService.Domain {

    public class Person {

        public Person() {
            Works = new HashSet<Work>();
        }

        [StringLength(10, MinimumLength = 10)]
        public string Id { get; set; }

        [StringLength(100, MinimumLength = 1)]
        public string LastName { get; set; }

        [StringLength(100, MinimumLength = 1)]
        public string FirstName { get; set; }

        [StringLength(4, MinimumLength = 4)]
        public string BirthYear { get; set; }


        [NotMapped]
        public virtual ICollection<Work> Works { get; set; }

#nullable enable
        [NotMapped]
        public virtual Death? Death { get; set; }
#nullable disable
    }
}
namespace DataService {

    public class DataContext: DbContext {
        public DbSet<Person> Persons { get; set; }
        public DbSet<Death> Deaths { get; set; }
        public DbSet<Work> Works { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            base.OnConfiguring(optionsBuilder);

            optionsBuilder.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
            optionsBuilder.EnableSensitiveDataLogging();
            optionsBuilder.UseNpgsql(Configuration.Shared.GetDatabaseString());
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Person>(builder => {
                builder.ToTable("person");
                builder.Property(x => x.Id).HasColumnName("nconst");
                builder.Property(x => x.FirstName).HasColumnName("firstname");
                builder.Property(x => x.LastName).HasColumnName("lastname");
                builder.Property(x => x.BirthYear).HasColumnName("birthyear");
                builder.HasKey(x => x.Id);
                builder.HasMany(x => x.Works).WithOne(x => x.Person).HasForeignKey(x => x.PersonId);
                builder.HasOne(x => x.Death).WithOne(x => x.Person).HasForeignKey<Death>(x => x.PersonId);
            });

            modelBuilder.Entity<Death>(builder => {
                builder.ToTable("death");
                builder.Property(x => x.PersonId).HasColumnName("nconst");
                builder.Property(x => x.DeathYear).HasColumnName("deathyear");
                builder.HasKey(x => x.PersonId);
                builder.HasOne(x => x.Person).WithOne(x => x.Death).HasForeignKey<Person>(x => x.Id);
            });

            modelBuilder.Entity<Work>(builder => {
                builder.ToTable("_work");
                builder.Property(x => x.TitleId).HasColumnName("tconst");
                builder.Property(x => x.PersonId).HasColumnName("nconst");
                builder.Property(x => x.Job).HasColumnName("job");
                builder.HasKey(x => new { x.TitleId, x.PersonId, x.Job });
                builder.HasOne(x => x.Title).WithMany(x => x.Staff).HasForeignKey(x => x.TitleId);
                builder.HasOne(x => x.Person).WithMany(x => x.Works).HasForeignKey(x => x.PersonId);
            });
        });
    }
}

问题是我可以获取 Person 实例,但它的虚拟属性都是 null。我知道它与 DataContext 中的外键有关,但我无法弄清楚...我错过了什么?

Person 获取操作

public Person GetPerson(string Id) {
    return Context.Persons.Find(Id);
}

失败的测试:

[Fact]
public void Test_GetDeath() {
    var person = DataService.GetPerson("nm0113225");
     Assert.NotNull(person);
     Assert.NotNull(person.Death); // <---- Failure
     Assert.Equal("2004", person.Death.DeathYear);
}

PS:我知道一些数据库属性可能会得到改进,但我现在不能。

PS2:这不是我的代码的完整版本,我删除了对我的问题无用的对象。

提前致谢

您必须将 include 添加到您的查询中

  Context.Persons. Include(i=>i.Works).FirstOrDefault(i=> i.Id==id );

并且如果您从 Death 中删除 [NotMapped],并添加 Death Id

      public int DeathId  { get; set; }
      public virtual Death Death { get; set; }

并修复你的死亡class,我相信一个人只能有一个死亡

 public class Death {
         [Key]
         public string Id {get; set;}

        [StringLength(4, MinimumLength = 4)]
        public string DeathYear { get; set; }
       
        public virtual Person Person { get; set; }
    }

你可以使用这个查询

Context.Persons.Include(i=>i.Works).Include(i=>i.Death).FirstOrDefault(i=>i.Id==id);