2013-08-06 77 views
0

首先为较差的标题道歉。绝对不知道如何描述这个问题!Linq基于渐进状态的查询

我有一个“关系”实体,它定义了2个用户之间的关系。

public class Relationship{ 
User User1{get;set;} 
User User2{get;set;} 
DateTime StateChangeDate {get;set;} 

//RelationshipState is an Enum with int values 
State RelationshipState State{get;set;} 
} 

关系状态示例。

public enum RelationshipState{ 
state1 = 1, 
state2 = 2, 
state3 = 3, 
state4 = 4 
} 

每次RelationshipState更改时都会创建关系实体。所以对于任何一对用户来说,都会有很多关系对象。随着最新的当前。

我试图查询任何关系对象,代表特定对用户在RelationshipState中的减少。

因此,所有用户的所有RelationshipObjects。该日期比具有更高RelationshipState的日期晚。

我发现很难弄清楚如何在不重复整个关系表的情况下完成此操作。

+0

与实际数据的任何尝试的某些代码示例和预期的结果将是非常适合的。 –

回答

1

首先,创建一个查询以返回列出所有状态更改的用户和子组的所有组合。有关更多信息,请参阅Google LINQ Group By。

然后使用您的收藏,通过查看最后两个状态更改并查看是否已关闭,过滤掉所有您不想要的。

下面是一个例子,在LinqPad试验作为C#程序:

public enum RelationshipState { 
state1 = 1, 
state2 = 2, 
state3 = 3, 
state4 = 4 
} 
public class User { 
    public int id {get;set;} 
} 
public class Relationship{ 
public User User1{get;set;} 
public User User2{get;set;} 
public DateTime StateChangeDate {get;set;} 

//RelationshipState is an Enum with int values 
public RelationshipState State {get;set;} 
} 

void Main() 
{ 


var rs=new List<Relationship>() { 
new Relationship{ User1=new User{id=1},User2=new User{id=2},StateChangeDate=DateTime.Parse("1/1/2013"),State=RelationshipState.state2}, 
new Relationship{ User1=new User{id=1},User2=new User{id=2},StateChangeDate=DateTime.Parse("1/2/2013"),State=RelationshipState.state3}, 
new Relationship{ User1=new User{id=1},User2=new User{id=3},StateChangeDate=DateTime.Parse("1/1/2013"),State=RelationshipState.state2}, 
new Relationship{ User1=new User{id=1},User2=new User{id=3},StateChangeDate=DateTime.Parse("1/2/2013"),State=RelationshipState.state1}, 
new Relationship{ User1=new User{id=2},User2=new User{id=3},StateChangeDate=DateTime.Parse("1/2/3013"),State=RelationshipState.state1} 
}; 

var result=rs.GroupBy(cm=>new {id1=cm.User1.id,id2=cm.User2.id},(key,group)=>new {Key1=key,Group1=group.OrderByDescending(g=>g.StateChangeDate)}) 
.Where(r=>r.Group1.Count()>1) // Remove Entries with only 1 status 
//.ToList() // This might be needed for Linq-to-Entities 
.Where(r=>r.Group1.First().State<r.Group1.Skip(1).First().State) // Only keep relationships where the state has gone done 
.Select(r=>r.Group1.First()) //Turn this back into Relationship objects 
; 

// Use this instead if you want to know if state ever had a higher state than it is currently 
// var result=rs.GroupBy(cm=>new {id1=cm.User1.id,id2=cm.User2.id},(key,group)=>new {Key1=key,Group1=group.OrderByDescending(g=>g.StateChangeDate)}) 
// .Where(r=>r.Group1.First().State<r.Group1.Max(g=>g.State)) 
// .Select(r=>r.Group1.First()) 
// ; 

result.Dump(); 
} 
+0

梦幻般的回应。不需要ToList。我没有想过如何移动它自己的团队。我试图用子查询来做到这一点。这是好得多 –

0

在数据库中创建一个存储的过程可以用一个光标来迭代的项目和它们之前与该项目配对它们关闭(和,然后过滤,以减小状态。)

除非的是,可以执行内查询为每个项目查找以前的值:

from item in table 
let previous = 
    (from innerItem in table 
    where previous.date < item.Date 
    select innerItem) 
    .Max(inner => inner.Date) 
where previous.State > item.State 
select item 

由于看起来效率低下,所以可能值得一试。也许,通过适当的索引和一个好的查询优化器(以及足够小的一组数据),它不会那么糟糕。如果速度慢得难以接受,那么用光标试用一个存储过程最有可能是最好的。