2016-11-10 10 views
1

У меня есть следующая структура базы данных для реализации Entity Framework (версия 5), которая работает в течение многих лет, но все медленнее и медленнее из-за каких-то циклических проблем с ссылками.Entity Framework not Lazy Loading FK Collection on Add

[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 на Sensor без него инстанцирования коллекции enitire существующих SensorSamples? В настоящее время у меня установлено AutoDetectChangesEnabled значение false и задержка DetectChanges до прямо SaveChanges. Это не имеет значения. Я не выключил LazyLoading, но, похоже, это не так, как я ожидал бы в этой ситуации. Я думаю, что все требования выполняются для LazyLoading, например, для публичных конструкторов без параметров. Я что-то пропустил? Есть идеи, почему это происходит? Благодарю.

+0

И почему вы не отключили ленивую загрузку ('LazyLoadingEnabled = false')? –

ответ

1

У меня есть очень хорошая идея, почему это происходит: когда EF загружает что-то из базы данных, он не возвращает ваш тип, а вместо этого возвращает класс, который происходит от вашего. Если у этого класса есть виртуальные свойства, из которых EF может вывести отношения, то этот класс реализует виртуальные свойства, чтобы при доступе они загружали связанные объекты из хранилища. Такая операция может стать довольно длинной, поскольку все больше и больше внешних ключей связаны с экземпляром.

Чтобы избежать этого, просто создайте экземпляр образца датчика, сопоставьте модель вашего бизнеса и хранилища и установите внешний ключ, который связывает образец с датчиком. Как только это будет сделано, добавьте образец в соответствующий DbSet в DbContext и сохраните изменения.

Было бы что-то вдоль линий:

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(); 

Sidenote:

ли воздерживаться от использования Ленивые функции виртуальной коллекции в EF, если вы не знаете, что результирующий набор хорошо ограничен.

+0

Спасибо за рекомендацию. Теперь, когда вы упомянули об этом, я не уверен, почему я изначально добавлял 'SensorSample' через' Sensor', вместо того, чтобы просто добавлять его непосредственно в 'DbContext'' SensorSamples' 'DbSet'. Наверное, это то, что происходит, когда вы возвращаетесь и анализируете 3-летний код. Это определенно решило проблему. – Psyfun

+0

Я точно знаю, как это чувствуется. @ Psyfun –