实体框架中的三元关系

时间:2012-04-02 19:20:21

标签: c# entity-framework

在Entity Framework 4.2中,我有一个Trips实体,可以有0 .. * PlacesOfInterest和0 .. *照片。景点有1个旅行和0 .. *照片。照片有1次旅行和0..1个景点。

当我尝试添加照片时,我使用此方法:

    public static Guid Create(string tripId, Model.Photo instance)
    {
        var context = new Model.POCOTripContext();
        var cleanPhoto = new Model.Photo();
        cleanPhoto.Id = Guid.NewGuid();
        cleanPhoto.Name = instance.Name;
        cleanPhoto.URL = instance.URL;
        //Relate the POI
        cleanPhoto.PlaceOfInterest = Library.PlaceOfInterest.Get(instance.PlaceOfInterestId);
        context.PlacesOfInterest.Attach(cleanPhoto.PlaceOfInterest);
        //Relate the trip
        cleanPhoto.Trip = Library.Trip.Get(new Guid(tripId));
        context.Trips.Attach(cleanPhoto.Trip);
        //Add the photo
        context.Photos.AddObject(cleanPhoto);
        context.SaveChanges();
        return cleanPhoto.Id;
    }

当我测试这个时,我会在附加旅行时得到以下信息:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

Trip确实出现在上下文对象中,但PlacesOfInterest也在Attach语句之前出现。我不明白这是如何运作的,有人可以澄清吗?

编辑:这是POI和Trip Getters

    public static Model.Trip Get(Guid tripId)
    {
        using (Model.POCOTripContext context = new Model.POCOTripContext())
        {
            var tripEntity = context.Trips.Include("PlacesOfInterest").Include("PlacesOfInterest.PoiAttributes").Include("Photos").FirstOrDefault(c => c.Id == tripId) ?? new Model.Trip();
            return tripEntity;
        }
    }

    public static Model.PlaceOfInterest Get(Guid poiId)
    {
        using (Model.POCOTripContext context = new Model.POCOTripContext())
        {
            var poiEntity = context.PlacesOfInterest.Include("PoiAttributes").FirstOrDefault(c => c.Id == poiId) ?? new Model.PlaceOfInterest();
            return poiEntity;
        }
    }

由于

取值

1 个答案:

答案 0 :(得分:1)

此...

context.Trips.Include("PlacesOfInterest")....

...将加载行程中的PlacesOfInterest。当您将旅程附加到其他上下文trip.PlacesOfInterest时也会附加。因为您之前已经附加了PlaceOfInterest(在集合中具有PlaceOfInterest的Id),所以您将使用相同的键附加两个相同类型的对象。这会导致异常。

您实际上可以简化代码:您不需要加载实体,因为您拥有主键。然后,您可以使用该密钥创建新实例并附加它:

cleanPhoto.PlaceOfInterest = new PlaceOfInterest
                             { Id = instance.PlaceOfInterestId };
context.PlacesOfInterest.Attach(cleanPhoto.PlaceOfInterest);

cleanPhoto.Trip = new Trip { Id = new Guid(tripId) };
context.Trips.Attach(cleanPhoto.Trip);