RIA Services не возвращает Включенный Тип Коллекции Собственности - PullRequest
3 голосов
/ 12 апреля 2010

У меня есть приложение WCF RIA Services и модель с типом UserRole, которая содержит коллекцию объектов UserPermission. Я использую .Include ("UserPermission") в доменной службе, и когда я отлаживаю его, я убедился, что он определенно содержит типы UserPermission перед возвратом.

Когда я отлаживаю клиент Silverlight 3, он возвращает UserRoles, но свойства UserPermission все пусты. Это те же самые UserRoles, которые показывают наличие UserPermissions для службы.

Поскольку на сервисе и клиенте все выглядит правильно, я сосредоточился на классе метаданных, но все равно не могу найти ничего неправильного.

[MetadataTypeAttribute(typeof(UserRole.UserRoleMetadata))]
public partial class UserRole
{
    internal sealed class UserRoleMetadata
    {
        public int RoleID;
        public string Name;

        [Include]
        [Association("UserPermissions", "RoleID", "PermissionID")]
        public EntityCollection<UserPermission> UserPermissions;
    }
}

Вот метод обслуживания домена:

public IEnumerable<UserRole> GetUserRoles()
{
    IEnumerable<UserRole> roles = this.ObjectContext.UserRole.Include("UserPermissions");
    return roles; // In debug, roles.First().UserPermissions.Count = 2 here
                  // For now, there is only one single role in the ObjectContext and it has
                  // two UserPermissions
}

Вот метод клиента Silverlight:

context.Load(context.GetUserRolesQuery(), loadOp =>
{
    IEnumerable<UserRole> roles = loadOp.Entities;
    // This should show 2, but shows 0:
    MessageBox.Show("Permissions loaded: " + roles.First().UserPermissions.Count.ToString());
}

Кто-нибудь знает что-нибудь, что может привести к потере этих включенных сущностей? Я делаю то же самое в нескольких других местах, и они работают.

1 Ответ

7 голосов
/ 15 апреля 2010

ОК, решено !Я взглянул на сериализованные данные, передаваемые между сервером и клиентом с помощью Fiddler , и обнаружил, что все вложенные типы фактически передаются, но отношения между ними не были правильными.После некоторых экспериментов, размышлений и онлайн-исследований выяснилось, что отношения «многие ко многим» в EF работают не так, как ожидалось , и если вы используете промежуточную таблицу для управления нужными отношениямичтобы включить эти таблицы в модель.

Чтобы заставить мое приложение работать, я сделал следующее:

1) Зашел в БД и обновил промежуточные таблицы (те, которые управляют многимиотношения ко многим) путем добавления столбца идентификатора первичного ключа.Как только это будет добавлено, EF-сгенерированная модель будет включать эти таблицы при обновлении.

2) Чтобы полностью стереть мою существующую модель, я использовал трюк переименования моих таблиц в БД, обновления модели, переименованияТаблицы БД возвращаются, а затем обновляются и выбирают таблицы, которые я хочу добавить.Это может быть излишним, но из-за проблем, с которыми я сталкивался в прошлом, я считаю, что это лучший способ обеспечить полную очистку таблиц.

3) Мне пришлось добавить все классы метаданных для новых промежуточных типова также обновить классы метаданных для существующих типов.Я написал фрагмент VS (тип 'meta') для добавления этих классов немного быстрее.Вы можете загрузить установщик здесь .

4) В дополнение к добавлению / обновлению всех существующих классов метаданных, вы должны убедиться, что все ваши 'AssociationAttributes' используют промежуточные типы и указывают сторонниеключевые свойства:

[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) Я обновил метод доменной службы с новой структурой:

public IEnumerable<UserRole> GetUserRoles()
{
    IEnumerable<UserRole> roles = this.ObjectContext.UserRole.Include("UserPermissionMembers.UserPermission");
    return roles;
}

6) Я обновил метод клиента, чтобы использовать новые типы.

context.Load(context.GetUserRolesQuery(), loadOp =>
{
    IEnumerable<UserRole> roles = loadOp.Entities;
    MessageBox.Show("Permissions loaded: " + roles.First().UserPermissionMembers.Count.ToString());
}

ПРИМЕЧАНИЕ. Даже зная проблему, потребовалось некоторое время, чтобы правильно настроить все атрибуты AssociationAttributes, чтобы они ссылались на правильные свойства.Если у вас возникли проблемы, я советую вам проверить их еще раз.

Это большая боль для чего-то, что должно быть более элегантным.Я еще не смотрел EF v4, но надеюсь, что все это улучшится.

...