Включите () в EF4, используя RIA Services Domain Service не загружается!
У меня возникли проблемы с возвратом нескольких объектов (полная загрузка) с помощью метода Include(). Я пытаюсь загрузить документы в приложение Silverlight, используя службы RIA. Модель данных состоит из следующих отношений:
Events.ID = EventParticipants.EventsID
EventParticipants.ParticipantUserID = Users.ID
Таким образом, в событии может быть много участников, а участник - ровно 1 пользователь.
Я могу нормально загрузить событие, но ничего не могу получить от дочерних отношений, указанных в операторе Include().
Когда я загружаю Событие, я пытаюсь включить (используя нетерпеливую загрузку) всех участников EventPartants и связанные с ними записи пользователя. В моей доменной службе у меня есть следующее:
public IQueryable<Event> GetEvents()
{
return this.ObjectContext.Events
.Include("EventParticipants")
.Include("EventParticipants.User");
}
Затем я беру возвращаемый IQueryable и загружаю его, используя свой контекст домена на стороне клиента, вот так:
DomainContext.Load(DomainContext.GetEventsQuery(), LoadOperationCompleted, true);
(обычно я бы фильтровал это, но я все упростил, чтобы разобраться в сути проблемы)
В моем LoadOperationCompleted у меня есть 2 цикла, которые я использую, чтобы увидеть, возвращаются ли участники события, но я никогда не получаю каких-либо участников из запроса. (в базе данных у меня определено 242 события... у всех есть участники)
private void LoadOperationCompleted(LoadOperation lo)
{
if (lo.Error != null)
{
Debugger.Break();
lo.MarkErrorAsHandled();
}
foreach (Event item in lo.Entities)
{
foreach (var particpant in item.EventParticipants)
{
Debug.WriteLine("{0} {1}", particpant.User.First, particpant.User.Last);
}
}
}
Я также изменил приведенный выше код (см. Ниже), чтобы он вращался через исходный контекст домена вместо коллекции сущностей, которая передается через параметры операции загрузки, но безрезультатно. (события есть, детей нет)
foreach (Event item in DomainContext.Events)
В моей модели данных есть три конструктора (все сгенерированные) с различными параметрами. В каждом я отключил ленивую загрузку так:
this.ContextOptions.LazyLoadingEnabled = false;
В представлении xml файла DataModel.edmx была аннотация. Я думаю, что это только для целей генерации... но я тоже изменил это так:
<EntityContainer Name="MyCrazyEntities" annotation:LazyLoadingEnabled="false">
Я определил отношения в моей базе данных SQL Server 2008. Дизайнер поднял их и создал все отношения и свойства навигации в моей модели. Осматривая их, они кажутся действительными. Если я полон пальца при написании сущностей в операторе включения, он выдаст ошибку, говорящую, что путь недопустим (или что-то в этом роде)... поэтому я считаю, что отношения существуют и являются функциональными (и я могу видеть их определения в дизайнерском коде и еще много чего).
Я удалил всю фильтрацию и, в частности, дополнительные объединения, которые я поместил в запрос перед его выполнением. Это должно было гарантировать, что я не столкнулся с проблемой с объединениями, изменяющими форму запроса и нарушающими Include(). Кажется, это большая проблема для людей, я удалил все соединения таким образом, чтобы изолировать проблему. Это не комбинация объединений и включений.
Я несколько раз перестраивал свои проекты Silverlight, в которых размещается служба домена и DLL-служба RIA Services, думая, что у меня неправильные настройки. Я использовал генератор классов POCO с EF, но потом прочитал, что вы не можете включить то же самое с POCO... так что я тоже отменил это и вернулся к генератору сущностей по умолчанию.
Я запустил профилировщик SQL Server и захватил SQL из базового запроса и одного с помощью Include(). Данные для включений возвращаются. Я подтвердил это, скопировав запрос из профилировщика и выпустив его напрямую. Упрощенная версия запроса заключается в следующем. Отношения действительны, и я вижу все связанные данные (например, имена участников, номера телефонов и т. Д.)
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
Однако, когда сущность возвращается, Event.EventParticipants EntityCollection становится пустым. К сожалению. Разочаровывающе. Больно. (Я не из "Ли")
Я искал в Интернете решения, но не нашел никого с той же проблемой, которая не была бы решена настройкой отложенной загрузки, комбинацией объединений и включений или неподходящими навигационными свойствами.
Я только что пропустил некоторые основные вещи? Есть ли основная концепция, которую я пропускаю? У меня есть другой проект от старого работодателя, где они выполняют ту же самую операцию, и это, кажется, работает. Поэтому я уверен, что это можно сделать. Только не мной??
Любая помощь с благодарностью. Я в своем уме. Заранее спасибо!
1 ответ
Вы пытались связать коллекцию в вашей модели с атрибутом состав / включение? это также указывает риа-сервисам на сериализацию коллекции сущностей, вот пара ссылок, которые помогут вам выбрать правильный путь
Руководство по атрибутам WCF RIA Services
WCF RIA Services Часть 5 - Метаданные и общие классы
Поддержка композиции в RIA Services
Вот пример из блога Тима:
Вам необходимо вручную отредактировать сгенерированный metadata.cs
файл (сохранить список изменений в файле.txt)
[Include]
public EntityCollection<Album> Albums;
Затем в доменном сервисе сделайте это:
public IQueryable<Artist> GetArtistsWithAlbums()
{
return this.ObjectContext.Artists.Include("Albums");
}