2011-08-28 70 views
0

我有一个自参考表“产品”具有下列结构(其中,d =草案和A =准)问题的LINQ查询

ID ParentID Status Name 
--------------------------- 
1 NULL  A  Foo 
2 1   A  Foo2 
3 NULL  D  Bar 
4 1   D  Foo3 

一排可以是“新”(其中PARENTID ==空)或可以是现有行的版本。所以我们可以从表格看到,“Foo”项目有3个版本,“Bar”只有1个版本。

我需要根据用户是否只能看到“已批准”项目或是否能够看到“草稿”来返回每个项目的最新版本。因此,例如

用户谁可以看到“d”将有:

3 NULL D 
4 1  D 

“最新”行中“富”与“酒吧”。

用户谁可以看到 “A” 将有:

2 1  A 

即。只有“已批准”版本。

由于提前,

何塞

+0

你的课程是怎样的?您使用的是LINQ提供程序?你可以有更长的'ParentID'链吗?例如:6的父亲是5,5的父亲是1。 – svick

+0

是否为ParentID +状态唯一? –

+0

类与数据表具有相同的结构。我正在使用linq 2 sql。深度将只有1(所以没有子行本身会有孩子)。 – jose

回答

0

这里是LINQ查询应为你工作:

bool hasDraftAccess = false; 

var query = DataContext.Records.AsQueryable(); 

if (!hasDraftAccess) { 
    query = query.Where(r => r.Status == 'A'); 
} 

var seriesQuery = query.Select(r => new { Record = r, SeriesID = r.ParentID ?? r.ID }); 
var latestQuery = seriesQuery.GroupBy(s => s.SeriesID).Select(g => g.OrderByDescending(s => s.Record.ID).First()); 
var resultsQuery = latestQuery.Select(s => s.Record); 
var results = resultsQuery.ToArray(); 

这里发生的事情:

  1. 首先,如果用户无权访问,添加WHERE子句以筛选出草稿记录
  2. 然后添加名为'SeriesID'的伪列,将所有相关版本分组到该列中。也就是说,让家长和相关的孩子分组很容易。
  3. 集团的相关记录,然后从中挑选哪个记录是最近
  4. 从匿名类型选择LINQ的实体,以便它是可更新的

我应该注意的是,如果你要改变你的数据的能力模式,你应该考虑添加一个名为InsertDate的列或类似的东西。现在我假设无论什么记录都有最高的ID是最新的。相反,添加DateTime字段并对其进行排序通常会更好。

我很抱歉,这实际上并没有使用Linq语法 - 我更喜欢流畅的编码样式 - 但如果您愿意的话,它可以很容易地转换为Linq语法。

+0

谢谢 - 这很好。有一件事 - 我不得不做第二次查询,使用“contains”从数据库中获取完整数据(在结果集合中使用ID) - 是否有一步可以完成这一步?谢谢。 – jose

+0

是的,看我更新的答案。 – emfurry

+0

非常感谢。 – jose

-1

完全未经测试 - 但这样的事情可能会奏效,如果我理解正确的问题。

可以看到批准

context.Table.Where(p => p.Status == "A") 

可以看到批准草案

context.Table.Where(p => p.Status == "D" || (p.Status == "A" && !context.Table.Any(q => q.Status == "D" && q.Parent == p.Parent)))