我有一个sql语句列表
List<IStatement>
突出课程包括:
UpdateStatement有一个
我有一个IsEqualTo扩展方法来比较From子句
我正在尝试使用Linq Aggregate运算符将更新语句合并到单个更新语句中,同时保留顺序以便最终列表。
我正在考虑使用聚合来尝试这样做 - 到目前为止我的代码是
Dim mergeUpdates = Function(statements As IList(Of IStatement), statement As IStatement)
If statements.Count = 0 Then Return statements.AddItem(statement)
If Not TypeOf statement Is UpdateStatement Then Return statements.AddItem(statement)
Dim u = DirectCast(statement, UpdateStatement)
Dim t = (From st In statements
Where TypeOf st Is UpdateStatement
Let uSt = DirectCast(st, UpdateStatement)
Where uSt.GetFrom.IsEqualTo(u.From)
Select uSt).First.AddSet(u.Set)
Return statements.AddItem(t)
End Function
Return statements.Aggregate(New List(Of IStatement), Function(ss, s) mergeUpdates(ss, s)))
但现在我不确定Linq Aggregate是否是正确的方法。 (我知道上面的内容不完整)
我很感激任何指向正确(FP)方式的指示。
答案 0 :(得分:1)
首先,您需要将相关的更新语句组合在一起:
var groupedStatements = statements
.GroupBy(s=>new {IsUpdate= (s is UpdateStatement), From=s.GetFrom()});
GroupBy会将相关的更新语句分组,即使它们在列表中不是连续的。如果您只想对连续的语句进行分组,则需要替代GroupBy,例如this或this。
这假设所有IStatements都有一个GetFrom(),如果不是,你需要一些与?
运算符相关的技巧。此外,它要求From
类实现IEquatable,以允许GroupBy运算符检查相同的from子句。如果没有,则需要将from子句转换为字符串或其他内容,以便进行比较。
然后组合每个更新组的元素,并保持其他组不变
var combinedStatements = groupedStatements
.SelectMany(group=>group.Key.IsUpdate
? Enumerable.Repeat<IStatement>(new UpdateStatement (group.Key.From, group.Select(s=>s.GetSets())),1)
: group.Select(s=>s);
在这里,您需要一种方法来创建一个新的UpdateStatement,就像一个构造函数,它接受一个from子句和一个IEnumerable的Set子句。 SelectMany将结果语句列表的列表折叠为单个语句列表。请注意,Enumerable.Repeat(s,1)用于创建只有一个元素的新IEnumerable。