Include() in EF4 using RIA Services Domain Service not loading!
I am having trouble returning multiple entities (eager loading) using the Include() method. I am trying to load the entites in a silverlight application using RIA services. The Data Model consists of the following relationships:
Events.ID = EventParticipants.EventsID
EventParticipants.ParticipantUserID = Users.IDSo an Event can have many participants and a participant is exactly 1 user.
I can load the Event just fine, but I cannot get anything out of the child relationships specified by the Include() statement.
When I load up an Event, I am trying to pull in (using eager loading) all the EventParticipants and their associated user record. In my domain service I have the following:
public IQueryable<Event> GetEvents()
{
return this.ObjectContext.Events
.Include("EventParticipants")
.Include("EventParticipants.User");
}
I then take the IQueryable that is returned and load it using my Domain Context on the client side like so:
DomainContext.Load(DomainContext.GetEventsQuery(), LoadOperationCompleted, true);
(normally I would filter this but I simplified everything to get to the heart of the problem)
In my LoadOperationCompleted I have 2 loops that I use to see if the Event Participants are returned but I never receive any participants back from the query. (in the database, I have 242 Events defined...all of which have participants)
private void LoadOperationCompleted(LoadOperation lo)
{
if (lo.Error != null)
{
Debugger.Break();
lo.MarkErrorAsHandled();
}
foreach (E开发者_开发技巧vent item in lo.Entities)
{
foreach (var particpant in item.EventParticipants)
{
Debug.WriteLine("{0} {1}", particpant.User.First, particpant.User.Last);
}
}
}
I have also modified the above code (see below) to spin through the original domain context instead of the entities collection that is passed in through the load operation parameters to no avail. (events are there, children are not)
foreach (Event item in DomainContext.Events)
In my Data Model, there are three constructors (all generated) with varying parameters. In each I have disabled lazy loading like so:
this.ContextOptions.LazyLoadingEnabled = false;
There was an annotation in the xml representation of the DataModel.edmx. I think this is just for generation purposes...but I changed that too like so:
<EntityContainer Name="MyCrazyEntities" annotation:LazyLoadingEnabled="false">
I have defined relationships in my SQL Server 2008 database. The designer picked these up and created all of the relationships and navigation properties in my model. Inspecting them, they appear valid. If I fat finger the spelling of the Entities in the include statement, it throws an error saying the path is not valid (or something to that effect)...so I believe the relationships exist and are functional (and I can see their definitions in the designer code and whatnot).
I have removed all the filtering and specifically the additional joins I have placed on the query before issuing it. This was to ensure I wasn't encountering the problem with joins changing the shape of the query and breaking the Includes(). Seems to be a big problem for people, I have eliminated all joins in this manner to isolate the problem. It is not a combination of joins and includes.
I have rebuilt my silverlight projects that house the domain service and RIA Services DLL a couple of times thinking I had some setting wrong. I have used the POCO class generator with EF but then read you can't include the same way with POCOs...so I scrapped that too and went back to the default entity generator.
I fired up SQL Server profiler and captured the SQL from a base query and one with Includes(). The data for the Includes ARE BEING RETURNED. I verified this by copying the query from profiler and issuing it directly. A simplified version of the query is as follows. The relationships are valid and I can see all the related data is there (i.e. participant names, phone numbers, etc)
SELECT
'trimmed fields for brevity>'
FROM ( SELECT
'trimmed fields for brevity>'
CASE WHEN ([Join1].[ID1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM [dbo].[Events] AS [Extent1]
LEFT OUTER JOIN (SELECT 'trimmed fields for brevity>'
FROM [dbo].[EventParticipants] AS [Extent2]
INNER JOIN [dbo].[Users] AS [Extent3] ON [Extent2].[ParticipantUsersID] = [Extent3].[ID] ) AS [Join1] ON [Extent1].[ID] = [Join1].[EventsID]
) AS [Project1]
ORDER BY [Project1].[ID] ASC, [Project1].[C1] ASC
However, when the entity is returned, the Event.EventParticipants EntityCollection is empty. Sadly. Frustratingly. Painfully. (I am out of "ly"s)
I have scoured the internet for solutions but haven't found anyone with the same problem that wasn't solved by the lazyloading setting, the combination of joins and includes or inappropriate navigation properties.
Have I just missed some basic thing? Is there a major concept that I am missing? I have another project from an old employer where they perform this same operation and it appears to work. So I am sure it can be done. Just not by me??
Any help is greatly appreciated. I am at my wits end. Thanks in advance!
Did you try attribute the collection on your model with the composition/include attribute? this tells ria services to serialize the entitycollection as well, heres a couple of links to get you on the right path
A guide through WCF RIA Services attributes
WCF RIA Services Part 5 - Metadata and Shared Classes
Composition Support in RIA Services
This is the example from Tim's blog:
You need to manually edit the generated metadata.cs
file (keep a list of changes in a .txt file)
[Include]
public EntityCollection<Album> Albums;
Then in the domain service do this:
public IQueryable<Artist> GetArtistsWithAlbums()
{
return this.ObjectContext.Artists.Include("Albums");
}
精彩评论