我有一个实体框架(版本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满足所有要求,例如拥有公共无参数构造函数。我错过了什么吗?任何想法为什么会这样?感谢。
答案 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虚拟集合功能,除非您知道结果集合是有限的。