RIA 服务不返回包含的类型集合属性

发布于 2024-08-28 18:18:59 字数 1466 浏览 2 评论 0原文

我有一个 WCF RIA 服务应用程序和一个具有 UserRole 类型的模型,其中包含 UserPermission 对象的集合。我在域服务中使用 .Include("UserPermission") ,当我调试它时,我已经验证它在返回之前肯定包含 UserPermission 类型。

当我调试 Silverlight 3 客户端时,它返回 UserRoles,但 UserPermission 属性均为空。这些是显示对服务具有 UserPermissions 的相同 UserRoles。

由于服务和客户端上的所有内容都显示正确,因此我将重点放在元数据类上,但仍然找不到任何错误。

[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());
}

有谁知道可能导致这些包含的实体丢失的任何事情吗?我在其他几个地方也做了同样的事情,它们都有效。

I have a WCF RIA Services app and a model with a UserRole type that contains a collection of UserPermission objects. I use .Include("UserPermission") in the domain service and when I debug it I've verified it definitely contains the UserPermission types before returning.

When I debug the Silverlight 3 client it returns the UserRoles but the UserPermission properties are all empty. These are the same UserRoles that show having UserPermissions on the service.

Since everything appears correct on the service and client, I'm focussing on the metadata class, but still can't find anything wrong.

[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;
    }
}

Here's the domain service method:

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
}

Here's the Silverlight client method:

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());
}

Does anyone know of anything that might cause a loss of these included entities? I do this same thing in several other places and they work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一生独一 2024-09-04 18:18:59

好的,解决了!我使用 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,但我希望它能改善这一切。

OK, solved it! I took a look at the serialized data being passed between the server and client using Fiddler and found that all the nested types were in fact being passed but the relationships between them weren't correct. After some tinkering, thinking, and online research, it turned out many-to-many relationships in the EF don't work as expected and if you're relying on an intermediary table to manage the relationships you need to include those tables in the model.

To get my app to work I did the following:

1) Went into the DB and updated the intermediary tables (the ones that manage the many-to-many relationships) by adding a primary key identity column. Once this is added the EF-generated model will include these tables when updated.

2) To wipe out my existing model completely, I used the trick of renaming my tables in the DB, updating the model, renaming the DB tables back, and then updating again and selecting the tables I want added. This might be overkill but due to issues I've had in the past I find it's the best way to ensure the tables are completely clean.

3) I had to add all the metadata classes for the new intermediate types as well as update the metadata classes for the existing types. I wrote a VS snippet (type 'meta') for adding these classes a little quicker. You can download the installer here.

4) In addition to adding/updating all the existing metadata classes, you need to ensure all your 'AssociationAttributes' use the intermediary types and specify the foreign key properties:

[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) I updated the domain service method with the new structure:

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

6) I updated the client method to utilize the new types.

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

NOTE: Even knowing the problem it still took a while to properly configure all the AssociationAttributes so that they refer to the correct properties. If you're having issues, I suggest you double-check there.

This is a lot of pain for something that should be more elegant. I haven't looked at EF v4 yet but I hope it improves all this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文