在代码优先模式下创建的EntityFramework类的navigation属性的值总是为null

本文关键字:属性 navigation null 类的 EntityFramework 代码 模式 创建 | 更新日期: 2023-09-27 18:14:02

我是EntityFramework的初学者。下面的代码是从我的项目中提取的。

public class User
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int UserId { get; set; }
    public virtual int UserType { get; set; }
}
public class Person : User
{
    public override int UserType
    {
        get
        {
            return 0;
        }
        set
        {
            base.UserType = 0;
        }
    }
    public string PersonName { get; set; }
    public ICollection<Sunny.Models.WorkExperience> WorkExperiences { get; set; }
}
public class WorkExperience
{
    [Key]
    public int ExperienceId { get; set; }
    public int PersonId { get; set; }
    public string Job { get; set; }
    [ForeignKey("PersonId")]
    public Person Person { get; set; }
}
public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        this.Map<User>(user => user.ToTable("User"));
        this.Map<Person>(person => person.ToTable("Person"));
    }
}
public class DbContext : System.Data.Entity.DbContext
{
    public DbContext() : base("name=Model")
    {
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new UserConfiguration());
        modelBuilder.Conventions.Remove<Conventions.PluralizingTableNameConvention>();
        base.OnModelCreating(modelBuilder);
    }
    public DbSet<User> Users { get; set; }
    public DbSet<Person> Persons { get; set; }
    public DbSet<WorkExperience> WorkExperiences { get; set; }
}
static void Main(string[] args)
{
    DbContext context = new Models.DbContext();
    Person person = new Models.Person();
    person.UserId = 1;
    person.PersonName = "Name";
    context.Persons.Add(person);
    WorkExperience experience = new Models.WorkExperience();
    experience.PersonId = 1;
    experience.Job = "Coder";
    context.WorkExperiences.Add(experience);
    context.SaveChanges();
    context = new DbContext();
    Console.Write(context.WorkExperiences.First().Person == null);
    Console.Read();
}

上面Main方法的运行结果显示为true,也就是说,属性WorkExperiences的值。Person总是空的,但是我已经向表中插入了数据。

如何让属性WorkExperiences。使用引用的键值加载人员?谢谢你的帮助。

在代码优先模式下创建的EntityFramework类的navigation属性的值总是为null

实体框架不会自动加载关联的实体,除非你特别查询它们。原因是,如果总是加载所有导航属性,那么加载的内容就会比预期的要多得多——如果有很多关系,那么即使是在一个简单的查询中,也可能会把数据库的大部分内容拉回来。想象一下,如果你去亚马逊,它对你的订单运行一个查询,然后包括这些订单中的所有产品,然后包括来自这些产品的所有卖家,然后包括来自这些卖家的所有产品,…

实体框架提供了几种技术来控制何时加载相关数据。

您可以使用DbExtensions.Include()强制它在原始查询中包含一个相关实体,这意味着需要访问数据库一次:

Console.Write(context.WorkExperiences.Include(w => w.Person).First().Person == null);

或者,你可以使用.Load()强制加载未加载的实体:

var firstWE = context.WorkExperiences.First();
firstWE.Reference("Person").Load();
Console.Write(firstWE.Person == null);

或者您可以启用延迟加载,这将使它在您第一次访问该属性时按需加载。您可以通过向它添加virtual来实现这一点(这允许EF能够向您的属性添加一些代码并根据需要加载):

public virtual Person Person { get; set; }