Vjacheslav Ravdin
Vjacheslav Ravdin

Reputation: 177

Adding nested entities to a database

I'm using MVC 4 and Entity Framework 5 Code First.

I have the following entities:

public class File
{
    public string Album { get; set; }

    public string Genre { get; set; }
}

public class Genre
{
    public string GenreId { get; set; }

    public virtual List<Album> Albums { get; set; }
}

public class Album
{
    public string AlbumId { get; set; }
}

I try to add them to a database:

        private readonly List<File> _files = new List<File>();

        var genres = _files
            .Select(x => new Genre { GenreId = x.Genre })
            .GroupBy(x => x.GenreId)
            .Select(x => x.First())
            .ToList();

        foreach (var genre in genres)
        {
            var genreId = genre.GenreId;

            var albums = _files
                .Where(x => x.Genre == genreId)
                .Select(x => new Album { AlbumId = x.Album })
                .GroupBy(x => x.AlbumId)
                .Select(x => x.First())
                .ToList();

            genre.Albums = albums;

            _unitOfWork.GenreRepository.Insert(genre);
        }

And I get the following error:

Violation of PRIMARY KEY constraint 'PK_dbo.Albums'. Cannot insert duplicate key in object 'dbo.Albums'. The duplicate key value is (Ooz).

The statement has been terminated.

The data I try to add looks like the following:

--Tribal 
----Ooz 
--Goa Trance 
----Ooz 
----Transient Dawn 
--Progressive Trance 
----Ooz 
----Music Prostitute: The Remixes 
--Psy-Trance 
----Music Prostitute: The Remixes 
--Downtempo 
----Transient Dawn 
--Ambient 
----Transient Dawn 

I see that I'm trying to add each album many times (because each album has many genres) but I don't know how to solve that issue.

Thanks for help!

Upvotes: 0

Views: 184

Answers (2)

Lzh
Lzh

Reputation: 3635

When creating the list of albums, try to get an album from the database before creating it.

Try this:

var albums = _files
            .Where(x => x.Genre == genreId)
            .Select(x => _yourDBContext.Albums.Where(album=>album.AlbumId == x.Album).FirstOrDefault() ?? 
                         new Album { AlbumId = x.Album })
            .GroupBy(x => x.AlbumId)
            .Select(x => x.First())
            .ToList();

The ?? is the null-coalescing operator, it chooses the second value if the first is null. I'm not sure, but hope this will help.

Upvotes: 1

matt-dot-net
matt-dot-net

Reputation: 4244

Instead of parsing into List<File> just insert into database at that step. Of course, you'll need to look to see if the genre exists, and if it does then insert files under that genre, if not then insert a new genre with the files already in the List<Album> Albums

Since you can do all of this in one context, entity will be very efficient for you. What I mean is that entity will track whether things are in the database or not and you can just build the tree of genres and albums and call one save changes.

Upvotes: 1

Related Questions