FanaticD
FanaticD

Reputation: 1467

EF: Inserting record to M:N table fails dues to duplicate key value

I have two models Film and Rating that are reflected in database as tables with same name, both of them have Guid Id and are in relation to each other via FilmRating table (without model).

To generate FilmRating table, I have in each model list that references the other, eg. List<Film> RatedFilms and List<Rating> Ratings.

The problem originates when I try to add record to Rating table, that would also add record to FilmRating table. I have following code:

 public void AddNewRating(Rating newRating, Film ratedFilm)
    {
        // Add rated film to the rating collection
        if(newRating.RatedFilms == null)
        {
            newRating.RatedFilms = new List<Film>();
        }

        newRating.RatedFilms.Add(ratedFilm);          

        using (var context = new IW5Context())
        {
            context.Ratings.Add(newRating);
            context.SaveChanges();
        }
    }

ratedFilm is object retrieved from database that represents film to which the rating should be related. IW5Context is simply class inheriting DbContext.

It says:

{"Violation of PRIMARY KEY constraint 'PK_dbo.Film'. Cannot insert duplicate key in object 'dbo.Film'. The duplicate key value is (5fd7ab30-b681-46d5-b34b-64afe0d1cfcb).\r\nThe statement has been terminated."}

From what I understand it tries to insert film to database, while I would expect it only to add records to Rating table and FilmRating table (and maybe check that film exists in Film table).

What should I do in order to get it to work?

Edit - adding Film & Rating models:

public class Rating : BaseObject
{
    public double RatingValue { get; set; }

    public string TextRating { get; set; }

    public DateTime TimeAdded;

    public List<Film> RatedFilms { get; set; }

}  
public class Film : BaseObject
{
...


  public List<Rating> Ratings
    {
        get; set;
    }
}

Id column is type of Guid and is inherited (together with string Name) from BaseObject.

AddNewRating is called from another project (but gets called) via method that is called from ICommand implementation method.

Upvotes: 0

Views: 619

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205829

If you are sure that the passed Film is an existing entity, then you should use DbSet<TEntity>.Attach method to let EF not attempt to insert it into the database:

using (var context = new IW5Context())
{
    context.Films.Attach(ratedFilm);
    context.Ratings.Add(newRating);
    context.SaveChanges();
}

Upvotes: 1

Related Questions