题
我有一个自引用类别表。每个类别都有一个 CategoryID、ParentCategoryID、CategoryName 等。每个类别可以具有任意数量的子类别,并且每个子类别可以具有任意数量的子类别,依此类推。所以基本上树的深度可以是 X 层。
然后,产品与叶(子)类别相关联。有没有办法使用 LINQ to SQL 获取任何给定类别的所有产品(这将是与其所有叶后代关联的所有产品)?
这感觉像是一个递归问题。使用存储过程更好吗?
解决方案
我认为 linq-to-sql 没有很好地解决这个问题。由于您使用的是 sql server 2005,因此您可以使用 CTE 进行分层查询。存储过程或内联查询(使用 DataContext.ExecuteQuery)都可以解决问题。
其他提示
这是使用 LINQ 的一个糟糕的仓促实现。不要使用这个:-)
public IQueryable GetCategories(Category parent)
{
var cats = (parent.Categories);
foreach (Category c in cats )
{
cats = cats .Concat(GetCategories(c));
}
return a;
}
高性能方法是创建一个插入/修改/删除触发器,该触发器维护一个完全不同的表,其中包含所有节点的所有祖先的节点-祖先对。这样,查找的时间复杂度为 O(N)。
要使用它来获取属于某个节点及其所有后代的所有产品,您只需选择以您的目标节点作为祖先的所有类别节点即可。此后,您只需选择属于任何这些类别的任何产品。
我处理这个问题的方法是使用一些扩展方法(过滤器)。我已经从我已经实现的项目中编写了一些示例代码。具体查看我填充 ParentPartner 对象和 SubPartners 列表的行。
public IQueryable<Partner> GetPartners()
{
return from p in db.Partners
select new Partner
{
PartnerId = p.PartnerId,
CompanyName = p.CompanyName,
Address1 = p.Address1,
Address2 = p.Address2,
Website = p.Website,
City = p.City,
State = p.State,
County = p.County,
Country = p.Country,
Zip = p.Zip,
ParentPartner = GetPartners().WithPartnerId(p.ParentPartnerId).ToList().SingleOrDefault(),
SubPartners = GetPartners().WithParentPartnerId(p.PartnerId).ToList()
};
}
public static IQueryable<Partner> WithPartnerId(this IQueryable<Partner> qry, int? partnerId)
{
return from t in qry
where t.PartnerId == partnerId
select t;
}
public static IQueryable<Partner> WithParentPartnerId(this IQueryable<Partner> qry, int? parentPartnerId)
{
return from p in qry
where p.ParentPartner.PartnerId == parentPartnerId
select p;
}
不隶属于 StackOverflow