实体框架不延迟加载FK集合

时间:2016-11-10 14:28:55

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

我有一个实体框架(版本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);

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

1 个答案:

答案 0 :(得分: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中的Lazy虚拟集合功能,除非您知道结果集合是有限的。