【问题标题】:Entity Framework not Lazy Loading FK Collection on Add实体框架不会在添加时延迟加载 FK 集合
【发布时间】:2016-11-10 14:28:55
【问题描述】:

我有以下用于实体框架(版本 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 并将其添加到Sensor 实例上的Samples 集合中。

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

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

【问题讨论】:

  • 你为什么不关闭延迟加载 (LazyLoadingEnabled=false)?

标签: c# entity-framework foreign-keys lazy-loading virtual


【解决方案1】:

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

为了避免这种情况,只需创建一个传感器示例实例,在您的业务模型和存储模型之间进行映射,并设置将示例与传感器关联的外键。完成后,将示例添加到 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 中使用惰性虚拟集合功能,除非您知道结果集是有界的。

【讨论】:

  • 感谢您的推荐。既然您提到了这一点,我不知道为什么我最初是通过Sensor 集合添加SensorSample,而不是直接将其添加到DbContextSensorSamplesDbSet。我想这就是你回去分析 3 年前的代码时会发生的事情。这绝对解决了问题。
  • 我知道那个人的感受。@Psyfun
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多