看起来很合理,我可能会更进一步,将组的结果列表转换为专为该工作设计的类:
record X(
DateTime Date,
int UserId,
int? TypeId1,
int? TypeId2,
int? TypeId3,
int? TypeId4
){
public X(IGrouping<(DateTime T,int U),System_Transaction> y):this(y.Key.T, y.Key.U, null, null, null, null){
foreach(var x in y){
_ = x.Type_Id switch {
1 => TypeId1 = x.Value,
2 => TypeId2 = x.Value,
3 => TypeId3 = x.Value,
4 => TypeId4 = x.Value,
_ => throw new NotImplementedException($"Type Id {x.Type_Id} is not handled")
};
}
}
然后加入你的分组
var groupTranDate = db.System_Transactions
.GroupBy(g => (g.Transaction_Date,g.User_Id))
.Select(g => new X(g))
.ToList();
记录就像一个类,只是写出来更简单;它有一个构造函数,可以转换 GroupBy 生成的分组;基本上构造函数首先调用另一个构造函数(你看不到,因为 C# 在幕后生成它)传递事务日期和用户是 - 设置这些属性。接下来,构造函数遍历分组(其行为类似于 YourClass 的列表,无论您的类被称为什么 - 请将类型名称更改为您的真实类名称),如果 Type_Id 为 1,则属性 TypeId1 最终分配了值等
在循环结束时,无论有多少项目(1 到 4 之间),您都会将 TypeIdX 属性设置为值(如果没有值,则保持为空)
LINQ 查询所需的唯一调整是将分组从匿名类型更改为元组,因为在创建它们的上下文之外使用 AT 很痛苦,并且使用 Select 将分组到我们的记录 X
如果您希望该记录在更熟悉的东西/在旧 .NET 中工作的类中,它看起来像:
class X(
public DateTime Date {get;set;},
public int UserId {get;set;},
public int? TypeId1 {get;set;},
public int? TypeId2 {get;set;},
public int? TypeId3 {get;set;},
public int? TypeId4 {get;set;}
){
public X(IGrouping<(DateTime T,int U),System_Transaction> y){
Date = T;
UserId = U;
foreach(var x in y){
if(x.Type_Id == 1) TypeId1 = x.Value;
else if(x.Type_Id == 2) TypeId2 = x.Value;
else if(x.Type_Id == 3) TypeId3 = x.Value;
else if(x.Type_Id == 4) TypeId4 = x.Value;
else throw new NotImplementedException($"Type Id {x.Type_Id} is not handled");
}
}
有一些方法可以让字典等变得可爱,以避免像那里那样在循环中写出巨大的 if/switch 块,但你仍然必须写出属性,除非你打算制作table 可以由具有 N 个键的字典驱动的仅显示事物,而不是您在代码中引用为具有属性 TypeId4 的某个 X 的对象。