I have NxN table, imagine:
User(id, ...) <- UserAddresses(id, userId, addressId, enabled, ...) -> Addresses(id, ...)
UserAddresses contains the FK to us
Another alternative option is using Load()
instead of Include()
:
var foundUser = context.User.Single(x => x.Id == USER_ID);
context.Entry(foundUser).Collection(u =>
u.UserAddresses).Query().Where(userAddress =>
userAddress.Enabled).Load();
Keep in mind that Load()
method could be ignored by EF in some scenarios:
If you are using EF along with the Lazy Loading feature, fetching your object brings all associated collections which have been marked as Virtual in your class. So by doing context.User.Single( x => x.id == USER_ID );
you'll get all UserAddresses associated to the User unless you turn off Lazy Loading for your collection by removing the Virtual
keyword from property in User class.
If you are adding/removing UserAddresses collection in your program and you call context.SaveChanges(); without disposing your context, next time when you load User object, UserAddresses collection will be loaded from EF context cache not from DB (your latest changes). In this case you need to Dispose your context and instantiate a new context before getting User from context. For example if you have your User with 5 items in your UserAddresses collection, and you make one of the items disabled(item.Enabled = false
) and then call context.SaveChanges()
without disposing your context, next time when you get User object from same context, it already has 5 items in its collection which comes from context cache and it ignores your Load()
method.
PS:
Lazy Loading feature is ON if all the conditions below applied:
There is no way in EF to partially load an association property. Try selecting into an anonymous type to take only what you need:
var result = context.User
.Where(u => u.Id == userId)
.Select(u => new {
Addresses = u.UserAddresses.Select(ua => ua.Address)
.Where(a => a.Enabled),
User = u // if you need this as well
})
.Single();
This won't load result.User.UserAddresses, but result.Addresses will have exactly what you want.
If you really want to return everything as part of the User class, you'd need to detach result.User and then update result.User.UserAddresses to point to result.Addresses.