Waleed
Waleed

Reputation: 1188

Updating relational entities

I have a scenario in which I need some help.

Let us assume that there is a User who listens to some type of Music.

class User
{   
    public virtual List<UserMusicType> Music { get; set; }
}

public class UserMusicType
{
    public int ID { get; set; }
    public MusicType name { get; set; }
}

public class MusicType
{
    public int ID { get; set; }
    public string Name { get; set; }
}

There is a form where I am asking users to check/select all types of Music he listens to. He selects 3 types namely { Pop, Rock, and Electronic }

CASE 1:

Now I want to update the User Entity and insert these 3 new types. From my understanding, I need to first remove whatever MusicTypes for this users were saved in the Database then insert these new types again. Is it a correct approach? Removing all previous and Inserting new ones? Or any other way to do it?

CASE 2:

I am taking MusicType names as string of course. Now while updating the User Entity, I'll have to first fetch the MusicType.ID after that I'll be able to do this:

user.Music.Add(new UserMusicType() { ID = SOME_ID });

Is there a better approach for this case?

I'll be glad to have some replies from experienced people in EF. I want to learn if there is an efficient way of doing it. Or even if my approach/Models are totally wrong or could be improved.

Upvotes: 2

Views: 74

Answers (2)

Farhad Jabiyev
Farhad Jabiyev

Reputation: 26635

First question:

Actually, it is a personal preference. Because, wouldn't want to delete all rows which belongs to that user and then insert them. I would compare the collection which is posted from the form with the rows which is stored in the database. Then, delete those entities from the database which are not exist in the collection anymore. And, insert new ones. Even, you can update those entities which has modified some additional details.

By the way, you can easily achieve this with the newly released EntityGraphOperations for Entity Framework Code First. I am the author of this product. And I have published it in the github, code-project and nuget. With the help of InsertOrUpdateGraph method, it will automatically set your entities as Added or Modified. And with the help of DeleteMissingEntities method, you can delete those entities which exists in the database, but not in the current collection.

// This will set the state of the main entity and all of it's navigational 
// properties as `Added` or `Modified`.
context.InsertOrUpdateGraph(user)
       .After(entity =>
       {
            // And this will delete missing UserMusicType objects.
            entity.HasCollection(p => p.Music)
               .DeleteMissingEntities();
       });  

You can read my article on Code-project with a step-by-step demonstration and a sample project is ready for downloading.

Second question:

I don't know on which platform you are developing your application. But, generally I am storing such libraries as MusicType in a cache. And use DropDownList element for rendering all types. When user posts the form, I am getting values rather than names of the selected types. So, no additional work is required.

Upvotes: 1

Haitham Shaddad
Haitham Shaddad

Reputation: 4456

First of all, you don't need the UserMusicType class, you can just declare the `User class as

class User
{   
    public virtual List<MusicType> Music { get; set; }
}

And entity framework will create a many to many relationship table in the database

As for the first question, it depends. If you use this relationship any where else, like payment or audit trail, then the best way would be to compare the posted values to the saved values, ex:

User selected Music 1, Music 2, Music 3 for the first time and saved, in this case the 3 records will be inserted. User edited his selection and chose Music 1,Music 3,Music 4, in this case you will get the values submitted which is 1,3,4 and retrieve the values stored in the database which is 1,2,3 Then you will get the new values which are the items that exist in the new values but not in the old, in this case it will be 4

You will get the removed values, which exist in the old but not in the new, in this case it will be Music 2. The rest can be ignored.

So, your query, will be add Music 4, remove Music 2.

If you don't depend on the relationship, then it is easier to just remove all user music and add the collection again.

As for the second part of your question, I assume you will display some chechboxes for the user, you should make the value for the checkbox control as the MusicType ID, and this is what will be posted to the backend and you can use it to link it to the user. ex:

user.Music.Add(new MusicType{ID=[selected ID ]}

You should not depend on the music name

Upvotes: 1

Related Questions