2016-11-10 121 views
1

我有一个实体框架(版本5)实现已经工作多年的以下数据库结构,但由于某种循环引用问题变得越来越慢。实体框架不延迟加载FK集合添加

[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,并将其添加到收藏SamplesSensor实例。

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

我怎样才能在Sensor样品添加到SensorSamples没有它存在的实例的SensorSamples的enitire收藏?我目前有AutoDetectChangesEnabled设置为false,并延迟DetectChanges,直到在SaveChanges之前。这没有什么区别。我还没有关闭LazyLoading,但它似乎并没有像我期望的那样踢进去。我认为LazyLoading满足所有要求,例如具有公共无参数构造函数。我错过了什么吗?任何想法为什么发生这种情况?谢谢。

+0

为什么你没有关闭延迟加载('LazyLoadingEnabled = false')? –

回答

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使用懒惰虚拟集功能避免,除非你知道结果集很好地界定。

+0

感谢您的建议。现在你提到了这一点,我不确定为什么我最初通过Sensor集合添加'SensorSample',而不是直接将它添加到'DbContext'的'SensorSamples''DbSet'。我想这就是你回去分析3年前的代码时发生的情况。这绝对解决了这个问题。 – Psyfun

+0

我完全知道那个人的感受。@ Psyfun –