0

I have two database tables :

1) Locations which has many Staffs

2) Staffs which has many Roles

If I want to load only related staffs which have Supervisor role for specific location I would do like this:

  var location = dbContext.Locations.Find(locationId);
  dbContext.Entry(location).Collection(b => b.Staffs).Query().Where(s => s.Roles.Any(r => r.Name=="Supervisor"));

My question is how to achieve explicit loading for related Staffs with supervisor role for all locations(I don't need for specific one as above)?

3
  • So you want all Staff with a supervisor role regardless of the location? Commented Oct 24, 2017 at 10:10
  • @Riv No, I want to load only Staff with Supervisor role for all locations inside locations table of course with locations data Commented Oct 24, 2017 at 10:11
  • EF is not designed to support partially loaded reference collections. So you will need to decide between loading all locations via include or separately querying the wanted location staff. Commented Oct 24, 2017 at 10:19

2 Answers 2

1

I did something similar for our implementation of the repository pattern. The key is to invoke Load at the end.

We had

public virtual void Load<TOut>(T entity, Expression<Func<T, ICollection<TOut>>> loadExpression, Expression<Func<TOut, bool>> filter) where TOut : class
{
    Context.Entry(entity).Collection(loadExpression).Query().Where(filter).Load();
}

So for your case you can try

dbContext.Entry(location).Collection(b => b.Staffs).Query()
    .Where(s => s.Roles.Any(r => r.Name=="Supervisor")).Load();

And then loop over all locations and load the references. Another option is to write an explicit Linq2Entities query for your case.

var locationWithStaff = (from location in dbContext.Locations
                         select new
                         {
                             location,
                             Staffs = (from staff in location.Staffs
                                       where staff.Roles.Any(r => r.Name=="Supervisor")
                                       select staff).ToList()
                          }).ToList();
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for answer.I think it's a good trick to implement that
1

You can use SelectMany to flatten the Staff list across all locations. Then you can filter based on the role

dbContext.Locations.SelectMany(b => b.Staffs).Where(s => s.Roles.Any(r => r.Name=="Supervisor"));

You could return an anonymous type in the SelectMany which would contain Location properties eg.:

dbContext.Locations.SelectMany(x => x.Staffs, (x, Staffs) => 
                   new { locationID = x.LocationID, SomeOtherProperty = x.OtherProperty , Staff = Staffs })
                  .Where(y => y.Staff.Roles.Any(z => z.Name == "Supervisor"));

3 Comments

This will only will load Staffs without the locations data , I think as @grek40 said "EF is not designed to support partially loaded reference collections"
@SimpleCode Do you need the entire Location entity or specific properties?
The entire location entities

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.