EF和链接表

时间:2012-12-11 21:57:22

标签: c# entity-framework

我想我在这里缺少一些简单的东西。我收到了错误:

  

“违反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。我显然是错的,但这是我想念的简单吗?

2 个答案:

答案 0 :(得分:2)

我认为您在featureTypeCodeRepositoryplaces.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 中说

  

除非你有一个非常好的   有充分理由不暴露外键属性你会省去很多痛苦   包括他们