2016-11-10 127 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 –