2

I have an entity Person, which has a related entity Hobby. This is a many to many relationship where a person can have several hobbies, and a hobby can be associated with many people. I want to create a ViewModel that allows new hobbies to be added and/or existing hobbies to be removed from a given Person entity.

The code below works, but I imagine it is rather inefficient.

var newHobbies = new List<Hobby>();

foreach (Hobby hobby in vm.Hobbies)
{
    var originalHobby = db.Hobbies.Find(hobby.HobbyID);
    newHobbies.Add(originalHobby);
}

originalPerson.Hobbies = newHobbies;

I prefer to do something like this:

var newHobbies = db.Hobbies.Where(x => vm.Hobbies.All(y => x.HobbyID == y.HobbyID)).ToList();   
originalPerson.Hobbies = newHobbies;

But I get an error:

Only primitive types or enumeration types are supported in this context.

How can I update related data without going to the database multiple times?

2
  • 'I imagine it is rather inefficient': how many hobbies can a person possibly have? Reducing execution time by an imperceptible amount is not worth making the code more obscure and harder to maintain. Commented Jul 31, 2015 at 19:54
  • Good point. Probably not more than 10. Only so much time in the day. Commented Jul 31, 2015 at 19:57

4 Answers 4

1

To avoid that exception you can select first the Ids from the vm.Hobbies collection and after that filter the hobbies you need:

var Ids=vm.Hobbies.Select(x=>x.HobbyID);

var newHobbies = db.Hobbies.Where(x => Ids.Contains(x.HobbyID)).ToList();
// another option could be: db.Hobbies.Where(x => Ids.Any(id=>id==x.HobbyID)).ToList();    
originalPerson.Hobbies = newHobbies;
Sign up to request clarification or add additional context in comments.

Comments

1

The message says that you can't use vm.Hobbies inside a LINQ-to-Entities query, only primitive types. This is what you can do:

var hobbyIds = vm.Hobbies.Select(h => h.HobbyId).ToList();
var newHobbies = db.Hobbies.Where(x => hobbyIds.Contains(x.HobbyID)).ToList();

Comments

0

The overall construction would be like such:

  • Your view takes the view model which displays the list of hobbies
  • You have an action to add a new Hobby passing a Hobby entity back as part of the action
  • You simply make a call back to the database to create the new association between the Person and Hobby
  • Add the Hobby entity to the collection in Person
  • Return passing the view model back to the view

In general EF and MVC are much easier to work with when you try to interact with your entities as whole entities and don't try to micromanage yourself things such as IDs, entity hydration, and so on.

2 Comments

What about updating existing hobbies? If I simply add them, won't my Hobbies table will have duplicates?
You just add the new one.
0

You could join by ID instead of fetching data from the DB:

originalPerson.Hobbies = db.Hobbies.Join(vm.Hobbies, h => h.ID, 
    v => v.HobbyID, (h, v) => h).ToList();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.