I worked with WCF RIA and Silverlight services and had some success in exposing a service that serves data retrieved from an ADO.NET entity data model modeled from an existing SQL Server 2008 Express database. The database defines many relationships between tables, which I hope to use the client side to bind data.
Everything went smoothly until I tried the following service method:
public IQueryable<Timeline> GetHighlights() { var self = from x in Database.Timelines where User.Id == x.UserId || User.Id == x.SenderId select x; var friends = from x in Database.FriendItems where User.Id == x.UserId from y in Database.Timelines where x.FriendId == y.UserId || x.FriendId == y.SenderId select y; return self.Concat(friends).OrderByDescending(s => s.Id); }
Note. A "user" is an internal property of a class that selects an authenticated user, and Database simply transfers the ObjectContext property (for convenience).
The Timeline entity contains 2 User and Sender navigation properties that are associated with the SilverfishUser entity. When I repeat the results from the query "I", I see that the previously mentioned properties were filled in by the current user (which is true). However, when I repeat the results of the query "friends", both properties have a value of zero (before being serialized to the client).
I tried setting:
this.ContextOptions.LazyLoadingEnabled = false; //and this.ContextOptions.ProxyCreationEnabled = false;
And I also tried to load links using the Include request method (with lazy loading with enabled and disabled) to no avail.
The only way I successfully populated the User and Sender properties of a Timeline object was using the following statement:
friends.ForEach(s => { if (!s.UserReference.IsLoaded) s.UserReference.Load(); if (!s.SenderReference.IsLoaded) s.SenderReference.Load(); });
From what I understand, the βDownloadβ operation leads to a separate query running in the database. As you can see, this presents a potentially inefficient situation where the user has many friends with many timeline messages. The exact situation I'm trying to avoid by disabling lazy loading. I want to return to the client a fully loaded object that can be associated with as few requests as possible.
I have already overcome one problem when relative properties were not serialized for the client by using the [Include] attribute in the metadata property definitions created by the domain service wizard. This question seems a bit more complicated, the solutions I tried were widely stated by others and should solve my problem theoretically, but they do not. Again, the only way I was able to successfully populate the object is to explicitly load links using the generated EntityReference <> property created for the property associated with it.
Any help, experience or information on this issue is welcome.
[EDIT] Updating some of my research when I execute this query:
var friends = Database.FriendItems .Include("Friend.Timeline") .Where(s => User.Id == s.UserId);
And to access the navigation properties ("friends.First (). Friend.Timeline.First (). User"), the value is not zero. This is only when I select a time frame in a new collection, adding something like:
.SelectMany(s => s.Friend.Timeline);
That navigation properties no longer matter. Now this is just an assumption, but I can only assume that it implements the property values ββin an instance of a new object, so it does not re-populate these properties in an attempt to avoid circular references? In any case, this is one feature of the brine to solve. Hopefully there is someone who knows more about this than I do.