如何在自引用对象中获得最顶层的父级

时间:2012-09-16 14:52:04

标签: database linq entity-framework entity-framework-4.1

更新 这是我从@Slauma讨论过的评论:

  

因为我需要获取所有连接到传递root的位置   类别。如你所见,如果我通过2,某些位置有类别   44和44是32岁的孩子,是2岁的孩子需要得到这个   地点。 LocationCategory是位置之间数据库中的N:N表   和PlaceCategories。不重要,但可以提供更好的图片。一世   在该地图上有地图和标记。我可以点击教育(id:2)   链接,我需要获取位置类别的根所在的所有标记   '2'(如在foursquare.com地图上)

我在数据库中有一个自引用表。 所以我创建了以下对象:

public class PlaceCategory
    {
        public int PlaceCategoryId { get; set; }
        public string Name{ get; set; }
        public int? ParentId { get; set; }

        public virtual PlaceCategory Parent { get; set; }
        public virtual ICollection<PlaceCategory> Children { get; set; }

        public string Icon { get; set; }
    }

因为Location对象可以有多个类别,所以我有LocationCategory对象:

public class LocationCategory
    {
        [Key, Column(Order = 1)]
        public int LocationId { get; set; }
        [Key, Column(Order = 2)]
        public int PlaceCategoryId { get; set; }
        public Guid UserId { get; set; }
        public DateTime CreatedOnDate { get; set; }
        public bool IsPrimary { get; set; }

        public virtual Location Location { get; set; }
        public virtual PlaceCategory PlaceCategory { get; set; }
        public virtual User User { get; set; }
    }

位置对象有:

public class Location
{
    ...
    public virtual ICollection<LocationCategory> LocationCategories { get; set; } 
    ...

在自我参考表的数据库中,我有:

root: Education (id:2, parentId:null)
child1: School(id:32, parentId:2) 
child2: Elementary(id:42,parentId:32), High(id:43,parentId:32), Higher(id:44,parentId:32) etc.

我必须根据传递的根类别列出位置列表。

var model = locationRepository.GetLocationss().Where(x => x.LocationCategories???); // but it's a list and don't know how to check top most parent here?

所以,如果我通过'2',我应该得到所有类别为2,32,42,43,44的物品

1 个答案:

答案 0 :(得分:3)

实体框架不支持此功能,除非您向每个rootCategoryId添加PlaceCategory并在检索位置时对该属性进行过滤,但一旦您进行了更深的嵌套,此方法将失败,您可能需要获取所有内容某些类别的位置不是root(但有自己的父级)。在这种情况下,存储根将无济于事。

此问题的泛化称为分层或递归查询。这是可以遍历层次结构并获取所有必需嵌套记录的查询。使用Common Table Expression alias CTE(需要SQL Server 2005或更高版本)可以使用SQL执行此操作。您可以创建此类查询并由dbContext.Database.SqlQuery直接执行。

对于带有.NET 4.5和EDMX(数据库优先)的EF 5.0,您还可以在SQL Server中将查询实现为表值函数,将其映射到EDMX并在Linq查询中使用它。