在代码优先模式下创建的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。使用引用的键值加载人员?谢谢你的帮助。
实体框架不会自动加载关联的实体,除非你特别查询它们。原因是,如果总是加载所有导航属性,那么加载的内容就会比预期的要多得多——如果有很多关系,那么即使是在一个简单的查询中,也可能会把数据库的大部分内容拉回来。想象一下,如果你去亚马逊,它对你的订单运行一个查询,然后包括这些订单中的所有产品,然后包括来自这些产品的所有卖家,然后包括来自这些卖家的所有产品,…
实体框架提供了几种技术来控制何时加载相关数据。
您可以使用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; }