I have the following two objects:
public class Artist { [Key] public string ArtistId { get; set; } public string Name { get; set; } public virtual ICollection<Genre> Genres { get; set; } } public class Genre { [Key] public int GenreId { get; set; } public string Name { get; set; } public virtual ICollection<Artist> Artist { get; set; } }
In my program, I create some artists and want to save them:
using (var context = new ArtistContext()) { var artists = _fullArtists.Select(x => x.Artist); foreach (var artist in artists) { context.Artists.AddOrUpdate(artist); } context.SaveChanges(); }
Entity Framework correctly created three tables:
Artist (ArtistId, Name)
Genre (GenreId, Name)
ArtistGenre (ArtistId, GenreId)
But unfortunately, when my sample data samples look like this:
var a1 = new Artist { Name = "a1" }; a1.Genres.Add(new Genre { Name="rock"}); var a2 = new Artist { Name = "a2" }; a2.Genres.Add(new Genre { Name="rock"});
It will create 2 entries in the Genre table:
Id name
1 rock
2 rock
instead of creating it once and then reusing it.
- Do you know that this is a configuration problem or how to tell EF not to insert duplicates and reuse existing ones instead?
Thank you in advance
Edit: Unfortunately, Sergey Berezovsky’s solution doesn't work (maybe I did something wrong: D)
Now I have the following:
using (var workUnit = WorkUnitFactory.CreateWorkUnit()) { var snapShot = new Snapshot { Date = DateTime.Now.Date };
ArtistExtensions.cs
public static class ArtistExtensions { public static Artist ToArtist(this FullArtistWrapper value, Snapshot snapShot) { if (value == null) { throw new ArgumentNullException(); } var artist = new Artist { ArtistId = value.Id, Name = value.Name }; var genres = value.Genres.Select(x => x.ToGenre()).ToList(); artist.Genres.AddRange(genres); return artist; } }
GenreExtensions.cs
public static class GenreExtensions { public static Genre ToGenre(this string value) { using (var workUnit = WorkUnitFactory.CreateWorkUnit()) { return workUnit.Repository<IGenreRepository>().GetGenres().FirstOrDefault(x => x.Name == value) ?? new Genre {Name = value}; } } }
Unfortunately, EF still inserts a duplicate of Genres into the database.
InsertEntities(...) :
public void InsertEntities<TPersistentEntity>(ICollection<TPersistentEntity> persistentEntitiesToBeInserted) where TPersistentEntity : PersistenceEntity { persistentEntitiesToBeInserted.ForEach(this.Add); } public void Add(PersistenceEntity entity) { var dbSet = this.Context.Set(entity.GetType()); dbSet.Add(entity); }
- Did I misunderstand Sergey’s answer or what could be another reason that EF is still inserting duplicates?
Thanks again