I have a WCF RIA Services app and a model with a UserRole type that contains a collection of UserPermission objects. I use .Include(\"UserPermission\") in the domain servic
OK, solved it! I took a look at the serialized data being passed between the server and client using Fiddler and found that all the nested types were in fact being passed but the relationships between them weren't correct. After some tinkering, thinking, and online research, it turned out many-to-many relationships in the EF don't work as expected and if you're relying on an intermediary table to manage the relationships you need to include those tables in the model.
To get my app to work I did the following:
1) Went into the DB and updated the intermediary tables (the ones that manage the many-to-many relationships) by adding a primary key identity column. Once this is added the EF-generated model will include these tables when updated.
2) To wipe out my existing model completely, I used the trick of renaming my tables in the DB, updating the model, renaming the DB tables back, and then updating again and selecting the tables I want added. This might be overkill but due to issues I've had in the past I find it's the best way to ensure the tables are completely clean.
3) I had to add all the metadata classes for the new intermediate types as well as update the metadata classes for the existing types. I wrote a VS snippet (type 'meta') for adding these classes a little quicker. You can download the installer here.
4) In addition to adding/updating all the existing metadata classes, you need to ensure all your 'AssociationAttributes' use the intermediary types and specify the foreign key properties:
[MetadataTypeAttribute(typeof(UserPermissionMembers.UserPermissionMembersMetadata))]
public partial class UserPermissionMembers
{
internal sealed class UserPermissionMembersMetadata
{
private UserPermissionMembersMetadata()
{}
public int ID;
public UserRole UserRole;
[Include]
[Association("UserPermission", "fkPermissionID", "PermissionID", IsForeignKey = true)]
public UserPermission UserPermission;
}
}
5) I updated the domain service method with the new structure:
public IEnumerable<UserRole> GetUserRoles()
{
IEnumerable<UserRole> roles = this.ObjectContext.UserRole.Include("UserPermissionMembers.UserPermission");
return roles;
}
6) I updated the client method to utilize the new types.
context.Load(context.GetUserRolesQuery(), loadOp =>
{
IEnumerable<UserRole> roles = loadOp.Entities;
MessageBox.Show("Permissions loaded: " + roles.First().UserPermissionMembers.Count.ToString());
}
NOTE: Even knowing the problem it still took a while to properly configure all the AssociationAttributes so that they refer to the correct properties. If you're having issues, I suggest you double-check there.
This is a lot of pain for something that should be more elegant. I haven't looked at EF v4 yet but I hope it improves all this.