简体   繁体   中英

Why does adding a child element to my entity framework try and insert a new parent?

I have a C# REST Service in WCF that sits on top of an EF 4.2 framework on SQL 2008. There are a few entities, but the two that matter are Trips and their children, PlacesOfInterest.

Here are the tables:

-- 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

Here are my POCO Models.

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; }
}

When I add a new PlaceOfInterest, the Entity Framework tries to insert a list, and I get a duplicate key error.

    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;
    }

I don't want it to insert that trip, I just want it to update the TripId column in the database. What am I doing wrong?

Very likely this line is the problem:

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

If Get loads the trip from the DB then it is loading it obviously in another context than context . You should use the same context. To write it ugly, something like: Get(context, new Guid(tripId)) and then use that injected context.

If Get just creates an instance of Trip ( new Trip { ... } ), you must attach it to the context:

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

But you all don't need that because you apparently have a foreign key property. Then this is enough:

cleanPoi.TripId = new Guid(tripId);

您应该从要保存的同一DataContext中获取cleanPoi.Trip。

In your Create method, you are getting the Trip and setting the PointOfInterest's Trip to that trip you grabbed. There are two issues with this:

  1. You are not handling the case where the Trip does not exist.
  2. You are setting a Reference to the Trip, which is being caught by the ChangeTracker in DbContext.

You can solve both problems by simply setting the TripId on the PointOfInterest object, and then wrapping the whole thing in a Try/Catch that handles the exception that the EF will throw if the foreign key does not exist.

Also, you need to dig into the InnerException details, as the Exception that comes back will have pretty specific info on exactly what the problem is. The problem could be that one of the GUIDs = Guid.Empty, and the one you are inserting also has an empty GUID. That would show evidence of a totally different problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM