Matt
Matt

Reputation: 4752

How to update related data using entity framework 6

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?

Upvotes: 2

Views: 764

Answers (4)

Sam FarajpourGhamari
Sam FarajpourGhamari

Reputation: 14741

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();

Upvotes: 0

ocuenca
ocuenca

Reputation: 39376

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;

Upvotes: 1

Gert Arnold
Gert Arnold

Reputation: 109251

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();

Upvotes: 1

Bigsby
Bigsby

Reputation: 952

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.

Upvotes: 0

Related Questions