1

I would like to simply create a relationship between two entities that already exists..

In my case I have an Album entity which might have multiple Genres(which also is a bunch of entities)

My Album model looks like this:

public class AlbumModel : IModel
{
    public List<GenreModel> Genres { get; set; }
    public ArtistModel Artist { get; set; }
    public Guid Id { get; set; }
    public string Title { get; set; }
    public float Price { get; set; }
    public string ArtUrl { get; set; }
}

I then want to create a relation ship between a Album model-object and a bunch of GenreModel-objects/entities..

In the "normal" entity framework I would just assign a new EntityKey.. but Im not quite sure of how to do this using code first.. I also noticed that some people has an extra property called xxxxId for the entity they want to create a reference between.. and then simply assign a value to the xxxxId property which some how magically creates the reference between the entities.. and I guess this works fine for a one to one or a one to many relationship.. but I guess that doesnt work for a many to many relationship..or?

Anyway.. this is my GenresModel:

public class GenreModel : IModel
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public List<AlbumModel> Albums { get; set; }
}

And this is what I tried before.. but this wont create the relationship..it will only simply create an additional entity/row in my database..

var artistRepository = new ArtistRepository();
        var genresRepository = new GenreRepository();

        #region Lordi
        context.Albums.Add
            (
                new AlbumModel
                {
                    Artist = artistRepository.GetByName("Lordi"),
                    ArtUrl = "http://upload.wikimedia.org/wikipedia/en/8/8f/The_Monster_Show.jpg",
                    Genres = new List<GenreModel> { genresRepository.GetByName("Rock"), genresRepository.GetByName("Hard rock") },
                    Id = Guid.NewGuid(),
                    Price = 3,
                    Title = "The Monster Show",
                }
            );
        context.Albums.Add
            (
                new AlbumModel
                {
                    Artist = artistRepository.GetByName("Lordi"),
                    ArtUrl = "http://www.nuclearblast.de/static/articles/157/157892.jpg/1000x1000.jpg",
                    Genres = new List<GenreModel> { genresRepository.GetByName("Rock"), genresRepository.GetByName("Hard rock") },
                    Id = Guid.NewGuid(),
                    Price = 10,
                    Title = "Zombilation - The Greatest Cuts",
                }
            );
        #endregion

...and for the record... no I dont listen to Lordi :).. just dummy data.. and for some wierd spooky reason Lordi was the first band that came in mind..

Thanks in advance!

Inx
  • 2,364
  • 7
  • 38
  • 55

2 Answers2

2

So basically you're trying to set up a many-to-many relationship in EF. I assume there's a table to link Albums and Genres in the database? If so you need to let EF know about the relationship and the table it's stored as I've explained here. You can find a lot of extra information by googling something like "set up many-to-many in Entity Framework".

On a side note you might also want to change your collection properties to virtual so instead of

public List<GenreModel> Genres { get; set; }

you would have

public virtual ICollection<GenreModel> Genres { get; set; }

This makes it faster by allowing EF to perform lazy loading on those properties.

Community
  • 1
  • 1
Manos Dilaverakis
  • 5,849
  • 4
  • 31
  • 57
  • Yes.. If I have understod this right.. the code-first creates this many to many table for me (in my case a table called GenreModelAlbumModel).. Thanks alot for the input regarding the virtual and the ICollection :) – Inx Mar 13 '13 at 07:43
1

Specifying those collection properties as you have done will automatically create a many-to-many linking table called GenreModelAlbumModels.

However, I suspect that your repository is preventing EF from knowing that there is a relationship. If you're not loading the GenreModel entities in the same data context, it may not know that there is a link between them. As an example, this code works:

    using (var context = new DataContext())
    {
        #region Lordi

        context.Albums.Add
            (
                new AlbumModel
                {
                    ArtUrl = "http://upload.wikimedia.org/wikipedia/en/8/8f/The_Monster_Show.jpg",
                    Genres = new List<GenreModel> { context.Genres.First(i => i.Name == "Rock"), context.Genres.First(i => i.Name == "Hard Rock") },
                    Id = Guid.NewGuid(),
                    Price = 3,
                    Title = "The Monster Show",
                }
            );

        context.SaveChanges();

        #endregion
    }

The GenreModels are connected to the same context that we're adding the AlbumModels to, so EF knows that there is a relationship between the entities.

To make sure it's working properly, look for that linking table in your DB. It will be hidden from you in the code.

samiz
  • 1,043
  • 1
  • 13
  • 21
  • Ok.. well I might be misstaken here.. but what if this application is an API where clients are allowed to post in an album for a specific artist that already exists in the database.. I then need to be able to set reference between the new album and the artist.. By simply doing: newAlbum.Artist = artistRepository.GetByName("Lordi") I would guess that EF would create an additional Lordi artist.. which isnt what I want.. – Inx Mar 13 '13 at 07:40
  • I also guess that in the example above.. I would also have to do the same thing with the Artist for the album..am I right? – Inx Mar 13 '13 at 07:44
  • Well turns out its was me beeing a moron.. :).. my repo created a new context.. instead of reusing/passing the former context down to the repo.. thanks alot for the help :)! – Inx Mar 13 '13 at 09:21