Linq渐进式基于状态的查询

本文关键字:状态 查询 渐进式 于状态 Linq | 更新日期: 2023-09-27 18:26:34

首先为糟糕的标题道歉。完全不知道如何描述这个问题!

我有一个"关系"实体,它定义了两个用户之间的关系。

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更改时,都会创建一个Relationship实体。因此,对于任何一对用户,都会有许多Relationship对象。最近的是最新的。

我正在尝试查询任何Relationship对象,该对象表示特定用户对的RelationshipState中的REDUCTION。

所有用户的所有RelationshipObjects。具有比具有较高RelationshipState的日期晚的日期。

我发现如果不迭代整个Relationship表,很难弄清楚如何实现这一点。

Linq渐进式基于状态的查询

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

然后使用你的收藏,通过查看最后两次状态更改,看看它是否已经消失,过滤掉所有你不想要的。

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

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();
}

在数据库中创建一个存储过程,该过程可以使用光标迭代项目,并将它们与前面的项目配对(然后过滤到递减状态)

除此之外,您可以执行内部查询,为每个项目查找以前的值:

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

尽管看起来效率很低,但也许值得一试。也许,有了合适的索引和一个好的查询优化器(以及足够小的数据集),情况就不会那么糟糕了。如果速度慢得令人无法接受,那么尝试使用游标的存储过程很可能是最好的。