我想我在这里缺少一些简单的东西。我收到了错误:
“违反PRIMARY KEY约束'PK_FeatureTypes'。无法在对象'dbo.FeatureTypeCodes'中插入重复键。重复键值为(28)。\ r \ n语句已终止”
我有一个FeatureType的查找/链接表 - (Mountain,Lake,River等)已经填充了数据,定义为:
[Table("FeatureTypeCodes")]
public class FeatureTypeCode {
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int FeatureTypeCodeID { get; set; }
public string Name { get; set; }
}
这与我的位置表/对象链接如下:
[Table("Places")]
public class Place {
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int PlaceID { get; set; }
public string Name { get; set; }
public FeatureTypeCode FeatureTypeCode { get; set; }
public ICollection<PlaceCoordinate> PlaceCoordinates { get; set; }
}
然后我从旧数据库加载它们(这是我的转换代码的一部分):
foreach (DataRow r in table.Rows) {
int ftID = Convert.ToInt32(r["FeatureTypeId"]);
Place temp = new Place {
PlaceID = Convert.ToInt32(r["PlaceID"]),
Name = r["PlaceName"].ToString(),
FeatureTypeCode = featureTypeCodeRepository.FeatureTypeCodes.FirstOrDefault(o=>o.FeatureTypeCodeID == ftID)
};
places.Add(temp);
}
在保存地点时,尝试插入与现有对象具有相同ID的新FeatureType对象时,会生成错误。我的想法是,通过从上下文加载FeatureType,它不会在保存Place对象时尝试插入新的FeatureType。我显然是错的,但这是我想念的简单吗?
答案 0 :(得分:2)
我认为您在featureTypeCodeRepository
和places.Add(temp);
中使用相同的DBContext对象。所以我认为基本上EF不会跟踪FeatureTypeCodes,因为它由一个上下文加载,并由另一个上下文保存。
答案 1 :(得分:0)
虽然我认为SimonEdström是对的(+1),但您也可以考虑在FeatureTypeId
类中公开原始外键字段(类似Place
?)。然后你可以简单地设置
FeatureTypeId = ftID;
如果您不确定FeatureTypeCodes
表中是否确实存在FK字段值,即使它具有不同的上下文,您也可以使用featureTypeCodeRepository
查询其存在性。使用Any()
是最便宜的方法:
var exists = featureTypeCodeRepository.FeatureTypeCodes
.Any(o => o.FeatureTypeCodeID == ftID)
在实体框架中执行此操作并不罕见。仅由引用组成的关系(如Place.FeatureTypeCode
)称为独立关联,具有引用和原始FK属性外键关联的关系。 Julia Lerman在她的书 DbContext 中说
除非你有一个非常好的 有充分理由不暴露外键属性你会省去很多痛苦 包括他们