Entity Framework 不是在添加时延迟加载 FK 集合

Entity Framework not Lazy Loading FK Collection on Add

我有以下用于 Entity Framework(版本 5)实施的数据库结构,该实施已工作多年,但由于某种循环引用问题而变得越来越慢。

[Table("Sensors", Schema = "Ems")]
public class Sensor
{
    public Sensor()
    {
        SensorSamples = new List<SensorSample>() as ICollection<SensorSample>;
    }

    [Key]
    public int Id { get; set; }

    [Required, MaxLength(128)]
    public string Name { get; set; }

    [MaxLength(256)]
    public string Description { get; set; }

    [MaxLength(128)]
    public string Location { get; set; }

    [Required]
    [MaxLength(15)]
    public string IPAddress { get; set; }

    [Required]
    public int Port { get; set; }

    [Required]
    public bool Enabled { get; set; }

    [Required, ForeignKey("Type")]
    public int SensorTypeId { get; set; }

    public virtual SensorType Type { get; set; }

    [Required, ForeignKey("Network")]
    public int SensorNetworkId { get; set; }

    public virtual SensorNetwork Network { get; set; }

    public virtual ICollection<SensorSample> SensorSamples { get; set; }
}

[Table("SensorSamples", Schema = "Ems")]
public class SensorSample
{
    public SensorSample()
    {
        SampleData = new List<SampleData>() as ICollection<SampleData>;
    }

    [Key]
    public int Id { get; set; }

    [Required, ForeignKey("Sensor")]
    public int SensorId { get; set; }

    public virtual Sensor Sensor { get; set; }

    [Required]
    public DateTime SampleTime { get; set; }

    [Required]
    public virtual ICollection<SampleData> SampleData { get; set; }
}

[Table("SampleData", Schema = "Ems")]
public class SampleData
{
    public SampleData()
    {
    }

    [Key]
    public int Id { get; set; }

    [Required, ForeignKey("DataType")]
    public int SampleDataTypeId { get; set; }

    public virtual SampleDataType DataType { get; set; }

    [Required, ForeignKey("Unit")]
    public int SampleUnitId { get; set; }

    public virtual SampleUnit Unit { get; set; }

    [Required, ForeignKey("Sample")]
    public int SensorSampleId { get; set; }

    public virtual SensorSample Sample { get; set; }

    [MaxLength(128)]
    public string Value { get; set; }
}

当我使用以下代码添加新的 SensorSample 时,添加第一个代码需要很长时间,因为它实例化了 SensorSample 并将其添加到 Samples 集合在 Sensor 个实例上。

Sensor sensor = GetSensor(1);
SensorSample sample = new SensorSample();
sample.SampleTime = d.Timestamp;
sample.SensorId = sensor.Id;
sensor.SensorSamples.Add(sample);

如何在 Sensor 上向 SensorSamples 添加示例而不实例化现有 SensorSamples 的整个集合?我目前将 AutoDetectChangesEnabled 设置为 false,并将 DetectChanges 延迟到 SaveChanges 之前。这没有区别。我没有关闭 LazyLoading 但在这种情况下它似乎并没有像我预期的那样启动。我认为 LazyLoading 满足所有要求,例如具有 public 无参数构造函数。我错过了什么吗?任何想法为什么会这样?谢谢。

我很清楚为什么会发生这种情况:当 EF 从数据库加载某些内容时,它不会 return 您的类型,而是 return 一个 class源自你的。如果此 class 具有 EF 可以从中推断出关系的虚拟属性,则此 class 会实现虚拟属性,以便在访问时从存储中加载关联的对象。随着越来越多的外键与实例相关联,这样的操作可能会变得很长。

为了避免这种情况,只需创建一个传感器示例实例,在您的业务模型和存储模型之间进行映射,并设置将示例与传感器相关联的外键。完成后,将示例添加到 DbContext 中的正确 DbSet 并保存更改。

大致如下:

var sample = new SensorSample();

.. Map properties and values from business to storage model

//Map the sensor foreign key for this sample
sample.SensorId = sensor.Id;

context.SensorSamples.Add(sample);
context.SaveChanges();

旁注:

不要在 EF 中使用惰性虚拟集合功能,除非您知道结果集是有界的。