Почему при добавлении дочернего элемента в мою структуру сущностей пытаются вставить нового родителя? - PullRequest
0 голосов
/ 29 марта 2012

У меня есть служба C # REST в WCF, которая находится поверх платформы EF 4.2 в SQL 2008. Есть несколько сущностей, но важны две: Trips и их потомки, PlacesOfInterest.

ЗдесьВот таблицы:

-- Creating table 'Trips'
CREATE TABLE [dbo].[Trips] (
[Id] uniqueidentifier  NOT NULL,
[Name] nvarchar(max)  NOT NULL,
[ArrivalDate] datetime  NULL,
[DepartureDate] datetime  NULL,
[WhereTo] nvarchar(max)  NOT NULL,
[CreatedDate] datetime  NULL,
[UpdatedDate] datetime  NULL,
[Album] nvarchar(max)  NOT NULL,
[UserToken] nvarchar(max)  NOT NULL,
[WallPostId] nvarchar(max)  NOT NULL
);
GO

-- Creating table 'PlacesOfInterest'
CREATE TABLE [dbo].[PlacesOfInterest] (
[Id] uniqueidentifier  NOT NULL,
[PhoneNumber] nvarchar(max)  NOT NULL,
[SmallPicture] nvarchar(max)  NOT NULL,
[LargePicture] nvarchar(max)  NOT NULL,
[HostId] nvarchar(max)  NOT NULL,
[HostName] nvarchar(max)  NOT NULL,
[Address1] nvarchar(max)  NOT NULL,
[Address2] nvarchar(max)  NOT NULL,
[Address3] nvarchar(max)  NOT NULL,
[City] nvarchar(max)  NOT NULL,
[State] nvarchar(max)  NOT NULL,
[Zip] nvarchar(max)  NOT NULL,
[Latitude] bigint  NOT NULL,
[Longitude] bigint  NOT NULL,
[URL] nvarchar(max)  NOT NULL,
[MapUrl] nvarchar(max)  NOT NULL,
[Hours] nvarchar(max)  NOT NULL,
[Name] nvarchar(max)  NOT NULL,
[PageId] nvarchar(max)  NOT NULL,
[Trip_Id] uniqueidentifier  NOT NULL,
[Category_Id] int  NULL
);
GO

Вот мои модели POCO.

public class Trip
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public DateTime ArrivalDate { get; set; }
    public DateTime DepartureDate { get; set; }
    public string WhereTo { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime UpdatedDate { get; set; }
    public string Album { get; set; }
    public List<PlaceOfInterest> PlacesOfInterest { get; set; }
    public List<Photo> Photos { get; set; }
    public string UserToken { get; set; }
    public string WallPostId { get; set; }
}

public class PlaceOfInterest
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string PhoneNumber { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    public long Latitude { get; set; }
    public long Longitude { get; set; }
    public string SmallPicture { get; set; }
    public string LargePicture { get; set; }
    public string HostId { get; set; }
    public string HostName { get; set; }
    public string URL { get; set; }
    public string MapUrl { get; set; }
    public string Hours { get; set; }
    public Category Category { get; set; }
    public List<Photo> Photos { get; set; }
    public List<Checkin> Checkins { get; set; }
    public List<PoiAttribute> PoiAttributes { get; set; }
    public Guid TripId { get; set; }
    public string PageId { get; set; }
    [IgnoreDataMember]
    public Trip Trip { get; set; }
}

Когда я добавляю новый PlaceOfInterest, Entity Framework пытается вставить список, и я получаю дубликат ключаошибка.

    public static Guid Create(string tripId, Model.PlaceOfInterest instance)
    {
        var context = new Model.POCOTripContext();
        var cleanPoi = new Model.PlaceOfInterest();
        cleanPoi.Id = Guid.NewGuid();
        cleanPoi.Address1 = instance.Address1;
        cleanPoi.Address2 = instance.Address2;
        cleanPoi.Address3 = instance.Address3;
        cleanPoi.City = instance.City;
        cleanPoi.HostId = instance.HostId;
        cleanPoi.HostName = instance.HostName;
        cleanPoi.Hours = instance.Hours;
        cleanPoi.LargePicture = instance.LargePicture;
        cleanPoi.Latitude = instance.Latitude;
        cleanPoi.Longitude = instance.Longitude;
        cleanPoi.MapUrl = instance.MapUrl;
        cleanPoi.Name = instance.Name;
        cleanPoi.PageId = instance.PageId;
        cleanPoi.PhoneNumber = instance.PhoneNumber;
        cleanPoi.SmallPicture = instance.PhoneNumber;
        cleanPoi.State = instance.State;
        cleanPoi.Trip = Library.Trip.Get(new Guid(tripId));
        cleanPoi.URL = instance.URL;
        cleanPoi.Zip = instance.Zip;
        context.PlacesOfInterest.AddObject(cleanPoi);
        context.SaveChanges();
        return cleanPoi.Id;
    }

Я не хочу вставлять эту поездку, я просто хочу обновить столбец TripId в базе данных.Что я делаю не так?

Ответы [ 3 ]

2 голосов
/ 29 марта 2012

Очень вероятно, что эта строка является проблемой:

cleanPoi.Trip = Library.Trip.Get(new Guid(tripId))

Если Get загружает отключение из БД, то оно загружает его явно в другом контексте, чем context.Вы должны использовать тот же контекст.Чтобы написать это некрасиво, что-то вроде: Get(context, new Guid(tripId)), а затем использовать этот введенный контекст.

Если Get просто создает экземпляр Trip (new Trip { ... }), вы должны присоединить его к контексту:

cleanPoi.Trip = Library.Trip.Get(new Guid(tripId))
context.Trips.Attach(cleanPoi.Trip);

Но вам всем это не нужно, потому что у вас, очевидно, есть свойство внешнего ключа.Тогда этого достаточно:

cleanPoi.TripId = new Guid(tripId);
1 голос
/ 29 марта 2012

В вашем методе Create вы получаете Trip и настраиваете PointOfInterest Trip на ту поездку, которую вы захватили. Есть две проблемы с этим:

  1. Вы не рассматриваете случай, когда Поездка не существует.
  2. Вы устанавливаете ссылку на поездку, которая перехватывается ChangeTracker в DbContext.

Вы можете решить обе проблемы, просто установив TripId для объекта PointOfInterest, а затем обернув все это в Try / Catch, которое обрабатывает исключение, которое EF сгенерирует, если внешний ключ не существует.

Кроме того, вам нужно углубиться в детали InnerException, поскольку возвращаемое исключение будет содержать довольно конкретную информацию о том, в чем именно заключается проблема. Проблема может заключаться в том, что один из GUID = Guid.Empty, а тот, который вы вставляете, также имеет пустой GUID. Это показало бы свидетельство совершенно другой проблемы.

1 голос
/ 29 марта 2012

Вы должны получить cleanPoi.Trip из того же DataContext, который вы сохраняете.

...