实体框架,代码先行.调用时未填充的子对象

本文关键字:填充 对象 调用 框架 代码 实体 | 更新日期: 2023-09-27 18:06:11

我要先掌握EF代码。当我在代码中调用对象时,我的领域模型设计似乎不支持对象的自动"填充"子对象。

模型:

public class Car
{
    [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    [Required,MaxLength(10)]
    public string Registration { get; set; }
    [MaxLength(30)]
    public string Make { get; set; }
    [MaxLength(45)]
    public string Model { get; set; }
    [Required]
    public Coordinates Coordinates { get; set; }
    [Required]
    public Client Client { get; set; }                    
}
public class Coordinates
{
    [Key, ForeignKey("Car")]
    public int Id { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    [Required]
    public Car Car { get; set; }
}

例如,我只需调用:

public List<Car> Get()
{            
    var cars = _context.Cars.ToList();
    return cars;
}

并且我的对象包含数据库中的所有Cars,但不包括Coordinates。数据库种子正确地创建了数据,但是我不能让EF自动引用CoordinatesClient。但我想,一旦我们解决了一个问题,另一个问题也会迎刃而解。

我做错了什么,我是否误解了如何做到这一点?

实体框架,代码先行.调用时未填充的子对象

您有几个选择:

  • 通过告诉EF Include()来急切加载相关实体。例如,你可以像这样加载Cars,包括CoordinatesClients:

    public List<Car> Get()
    {            
        var cars = _context.Cars
            .Include(car => car.Coordinates)
            .Include(car => car.Client)
            .ToList();
        return cars;
    }
    
  • 通过声明导航属性virtual来延迟加载相关实体,从而告诉EF在第一次访问时加载它们。确保你没有像这样为你的上下文禁用延迟加载:

    this.Configuration.LazyLoadingEnabled = false;

一个简短的例子如下:

public class Car
{
    // ... the other properties like in your class definition above
    public virtual Coordinates Coordinates { get; set;}
}
public void Get()
{
    var cars = _context.Cars.ToList();
    var coordinates = cars.First().Coordinates; // EF loads the Coordinates of the first car NOW!
}
  • 显式加载相关实体到上下文。然后,上下文将为您填充导航属性。如下所示:

    public List<Car> Get()
    {
        // get all cars
        var cars = _context.Cars.ToList();
        // get all coordinates: the context will populate the Coordinates 
        // property on the cars loaded above
        var coordinates = _context.Coordinates.ToList();
        return cars;
    }
    

您没有Coordinates的原因是因为它不包含在查询中。有多种方法可以将它包含在结果中:

  1. _context.Cars.Include(car => car.Coordinates).ToList();—它将在一次查询中获取具有坐标的汽车
  2. 如果你不需要Coordinates为所有的汽车,你可以做以下事情:使Coordinates属性虚拟,然后当你得到汽车,你可以得到Coordinates只有他们的子集,如果你需要和单独的调用将作出对数据库的每个属性"获得"访问。您还将在调试器中看到EF为您创建了动态类,因此您必须将其设置为virtual