来自OData feed的多对多查询

时间:2012-03-25 21:40:10

标签: .net linq odata

我正在尝试从Windows Phone 7 Silverlight客户端消费odata feed。基本上是组和用户之间的多对多数据关系,它们之间有UserGroup表。当用户登录时,我需要使用她的UserId查询她所属的组。我的数据类如下

[DataServiceKey("Id")]
public class Group
{
    public Guid Id { get; set; }
    public string GroupTag { get; set; }
    public DateTime DateCreated { get; set; }

    [ForeignKey("GroupOwner")]
    public Guid? GroupOwnerId { get; set; }
    public virtual Person GroupOwner { get; set; }

    public bool IsActive { get; set; }

    public virtual ICollection<GroupUser> GroupUsers { get; set; }
}

[DataServiceKey("Id")]
public class GroupUser
{
    public Guid Id { get; set; }

    [ForeignKey("Group")]
    public Guid GroupId { get; set; }
    public virtual Group Group { get; set; }

    [ForeignKey("Person")]
    public Guid PersonId { get; set; }
    public virtual Person Person { get; set; }
    public bool IsActive { get; set; }
}
 [DataServiceKey("Id")]
public class User
{
    public Guid Id { get; set; }
    public string Username { get; set; }
    public string  Password { get; set; }
    public virtual ICollection<GroupUser> UserGroups { get; set; }
    public virtual ICollection<Group> MyGroups { get; set; }
}

我已经尝试了所有我知道的结果,但无论我做什么,我都会一个接一个错误。没有2个我不想做的查询,因为它太乱了,有没有解决方案?

------ ------更新

从研究的漫长夜晚,我发现odata有不支持'Any'和'All'类型查询的限制,所以我的查询目前是不可能的。我还从here发现我可以稍微修改我对poco类的实现来表示多对多的关系而不明确定义中间的类,这可能有助于我解决这个导航问题。 我仍在处理它,因为我在定义导航属性时遇到了问题,但是只要我有解决方案,我就会把它放在这里,这样它就可以帮助其他一些不幸的旅行者走上这条道路。 / p>

3 个答案:

答案 0 :(得分:3)

最近将任何/所有支持添加到OData协议中。以下是两篇博客文章,其中包含有关OData中Any / All的一些信息:

Support for Any and All

Even More Any and All

ODTI的.NET实现,即WCF数据服务,也有Any/All support。当然,为了利用这一点,您正在与之交互的服务器必须支持Any / All。

答案 1 :(得分:1)

任何/所有问题的解决方法是使用webget在服务器端执行任何/所有过滤功能。将返回值设置为可查询,它将允许您在查询调用中使用标准odata约定和自定义筛选功能。

即。构建Web get之后的查询调用会像这样工作。

http://myServer:8000/MyService.svc/MyCustomFilteringWebGet?FilteringData=User/groups&$inlinecount=allpages

[WebGet]
public IQueryable<User> MyCustomFilteringWebGet(string FilteringData = null)
{
  return //Return any/all filtered data here. 
}

答案 2 :(得分:1)

所以这就是我最终为我的odata服务实现的方式。 首先,我不得不重新构建数据,取消规范化表GroupUser并在对象本身上定义相关集合:

[DataServiceKey("Id")]
public class Group
{
    public Guid Id { get; set; }
    public string GroupTag { get; set; }
    public DateTime DateCreated { get; set; }

    [ForeignKey("GroupOwner")]
    public Guid? GroupOwnerId { get; set; }
    public virtual Person GroupOwner { get; set; }

    public bool IsActive { get; set; }

    //his represents the many-to-many relationship
    public virtual ICollection<User> GroupMembers { get; set; }
}


[DataServiceKey("Id")]
public class User
{
  public Guid Id { get; set; }
  public string Username { get; set; }
  public string  Password { get; set; }

  //This represents the many-to-many relationship
  public virtual ICollection<Group> MembersOfGroups { get; set; }

  //This represents the 'GroupOwner' ForeignKey relationship
  public virtual ICollection<Group> MyGroups { get; set; }
}

在datacontext类中,我将覆盖OnModelCreating方法,如下所示

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasMany(p => p.MemberOfGroups).
            WithMany(c => c.GroupMembers)
            .Map(t=>t.MapLeftKey("GroupId")
                .MapRightKey("UserId")
                .ToTable("GroupUsers"));

    }

这基本上使实体框架能够深入了解我希望如何定义模型,从而覆盖传统实现。我认为理解上述陈述的最简单方法是将其作为声明如下:

用户实体可以有许多(有很多)MemberOfGroups,每个都可以与'许多'GroupMembers存在(因此有多对多关系),左表(Group)的foreignkey字段应该被称为GroupId和for右表(User)应该被称为UserId,这些应该被映射到一个名为“GroupUsers”的表。

如果您查看实体框架生成的数据表,您将找到第三个名为GroupUsers的表,其中包含两列:UserId和GroupId作为组合主键,每个表引用与相应实体表的外键关系。< / p>

通过这种方式,您可以轻松查询odata服务,就好像两个集合都是相应父实体的一对多关系一样。我希望这有助于某人。