I have a MainBusinessLine type with an ObservableCollection of type Group, and a method that I call from a DomainService the returns a queryable list of MainBusinessLines. So in this method I have confirmed that all the appropriate Groups are added to the MainBusinessLines Groups collection. But when the entities are loaded in the client silverlight application it's missing pretty much all of them. But the kicker is that the MainBusinessLine has another collection and it does contain all the appropriate entities after the client load operation. And my Association Attributes are the same way, meaning the parameters for thisKey and otherKey are set similar.
I am also creating POCO classes instead of using the EntityFramework. Here is a sample of my MainBusinessLine class:
[Serializable,
DataContract]
public class MainBusinessLine : BaseDataContract
{
public MainBusinessLine()
{
}
private int _MainBusinessLineID;
[Key,
DataMember,
Required]
public int MainBusinessLineID
{
get
{
return _MainBusinessLineID;
}
set
{
if (_MainBusinessLineID == value)
return;
ReportPropertyChanging("MainBusinessLineID");
_MainBusinessLineID = value;
ReportPropertyChanged("MainBusinessLineID");
}
}
private ObservableCollection<LOBs> _DefaultLOBs;
[DataMember,
XmlIgnore,
SoapIgnore,
Include,
Association("DefaultLOBsCollection", "MainBusinessLineID", "MainBusinessLineID")]
public ObservableCollection<LOBs> DefaultLOBs
{
get
{
return _DefaultLOBs;
}
set
{
ReportPropertyChanging("DefaultLOBs");
_DefaultLOBs = value;
ReportPropertyChanged("DefaultLOBs");
}
}
private ObservableCollection<Groups> _Groups;
[DataMember,
Include,
Association("GroupsCollection", "MainBusinessLineID", "MainBusinessLineID")]
public ObservableCollection<Groups> Groups
{
get
{
return _Groups;
}
set
{
ReportPropertyChanging("Groups");
_Groups = value;
ReportPropertyChanged("Groups");
}
}
}
And here are the LOBs and Groups classes:
[Serializable,
DataContract]
public class LOBs : BaseDataContract
{
private int _LOBID;
[Key,
DataMember,
Required]
public int LOBID
{
get
{
return _LOBID;
}
set
{
if (_LOBID == value)
return;
ReportPropertyChanging("LOBID");
_LOBID = value;
ReportPropertyChanged("LOBID");
}
}
private int _GroupID;
[DataMember]
public int GroupID
{
get
{
return _GroupID;
}
set
{
if (_GroupID == value)
return;
ReportPropertyChanging("GroupID");
_GroupID = value;
ReportPropertyChanged("GroupID");
}
}
private int _MainBusinessLineID;
[DataMember]
public int MainBusinessLineID
{
get
{
return _MainBusinessLineID;
}
set
{
if (_MainBusinessLineID == value)
return;
ReportPropertyChanging("MainBusinessLineID");
_MainBusinessLineID = value;
ReportPropertyChanged("MainBusinessLineID");
}
}
}
[Serializable,
DataContract]
public class Groups : BaseDataContract
{
private int _GroupID;
[Key,
DataMember,
Required]
public int GroupID
{
get
{
return _GroupID;
}
set
{
if (_GroupID == value)
return;
ReportPropertyChanging("GroupID");
_GroupID = value;
ReportPropertyChanged("GroupID");
}
}
private int _MainBusinessLineID;
[DataMember]
public int MainBusinessLineID
{
get
{
return _MainBusinessLineID;
}
set
{
if (_MainBusinessLineID == value)
return;
ReportPropertyChanging("MainBusinessLineID");
_MainBusinessLineID = value;
ReportPropertyChanged("MainBusinessLineID");
}
}
}
Could someone please tell me what I may have wrong here? I have a feeling it has something to do with the way I'm setting the association attributes. Thanks
Ok, so I finally figured out what I was doing wrong. So I'm going to give a brief, yet detailed, explanation of how to set up a "POCO DomainService". I'm sure this is not the only way, but it's the simplest way I found, and it works. And hopefully this will save someone else a weeks worth of headaches and frustrations.
So basically, my situation was that I had a MainBusinessLine type that had a Groups collection and a DefaultLOBs collection. But what I didn't include was that I had a GroupsReference type, that had a MainBusinessLineID property and a GroupID property. When I retrieved my data I went ahead and looped through the GroupsReference types and added the Groups to the parent MainBusinessLine's GroupsCollection. And the same thing for the DefaultLOBsCollection as well. So I was populating the collection before they were being "Queried" from the DomainService, and there was the issue.
After thinking about it and reading all I could find, the Gods of Coding finally took pity on me and struck me with the answer. I would retrieve the data and create Lists of each type WITHOUT populating any of the collection properties that are associations. And then return the Lists AsQuerable() in their appropriate Query Method, and the entities that are generated on the client will have their EntityCollections full.
So in conclusion, if you have the Include and Association attributes set with the correct keys and not try to force the data, then you should have success. I'll include my new sample code and hopefully this will helpful for someone else.
[Serializable,
DataContract]
public class MainBusinessLine : BaseDataContract
{
Int32 _MainBusinessLineID;
[Key,
DataMember,
Required]
public Int32 MainBusinessLineID
{
get
{
return _MainBusinessLineID;
}
set
{
if (_MainBusinessLineID == value)
return;
_MainBusinessLineID = value;
ReportPropertyChanged("MainBusinessLineID");
}
}
ObservableCollection<GroupsReference> _GroupsReferenceCollection;
[DataMember,
Include,
Association("GroupsReferenceCollection", "MainBusinessLineID", "MainBusinessLineID")]
public ObservableCollection<GroupsReference> GroupsReferenceCollection
{
get
{
return _GroupsReferenceCollection;
}
set
{
_GroupsReferenceCollection = value;
ReportPropertyChanged("GroupsReferenceCollection");
}
}
}
[Serializable,
DataContract]
public class GroupsReference : BaseDataContract
{
Int32 _GroupsReferenceID;
[Key,
DataMember,
Required]
public Int32 GroupsReferenceID
{
get
{
return _GroupsReferenceID;
}
set
{
if (_GroupsReferenceID == value)
return;
_GroupsReferenceID = value;
ReportPropertyChanged("GroupsReferenceID");
}
}
Int32 _MainBusinessLineID;
[DataMember,
Required]
public Int32 MainBusinessLineID
{
get
{
return _MainBusinessLineID;
}
set
{
if (_MainBusinessLineID == value)
return;
_MainBusinessLineID = value;
ReportPropertyChanged("MainBusinessLineID");
}
}
Int32 _GroupID;
[DataMember,
Required]
public Int32 GroupID
{
get
{
return _GroupID;
}
set
{
if (_GroupID == value)
return;
_GroupID = value;
ReportPropertyChanged("GroupID");
}
}
}
[Serializable,
DataContract]
public class Group : BaseDataContract
{
Int32 _GroupID;
[Key,
DataMember,
Required]
public Int32 GroupID
{
get
{
return _GroupID;
}
set
{
if (_GroupID == value)
return;
_GroupID = value;
ReportPropertyChanged("GroupID");
}
}
ObservableCollection<GroupsReference> _GroupsReferenceCollection;
[DataMember,
Include,
Association("GroupsReferenceCollection", "GroupID", "GroupID")]
public ObservableCollection<GroupsReference> GroupsReferenceCollection
{
get
{
return _GroupsReferenceCollection;
}
set
{
_GroupsReferenceCollection = value;
ReportPropertyChanged("GroupsReferenceCollection");
}
}
}
[EnableClientAccess(RequiresSecureEndpoint = false)]
public class DentalAdminPortalDomainService : DomainService
{
public DentalAdminPortalDomainService()
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
}
[Query]
public IQueryable<MainBusinessLine> GetMainBusinessLines()
{
return DataRepository.GetMainBusinessLines().AsQueryable<MainBusinessLine>();
}
[Query]
public IQueryable<Groups> GetGroups()
{
return DataRepository.GetGroups().AsQueryable<Groups>();
}
[Query]
public IQueryable<GroupLOBList> GetGroupsReference()
{
return DataRepository.GetGroupsReferences().AsQueryable<GroupsReference>();
}
}
And once again, all I do is get the data from the database. Use reflection to create instances of each type, set the property values (no collections are filled), and add them to a list. Then return the lists to the client. The rest is all done by the generated code.