标题非常糟糕,所以让我试着用代码解释一下。我有一个名为Change
的实体,它有一个ChangeDetail
个实体的集合。我想将Change
个实体的集合投影到名为ChangeListItem
的DTO。我一直在搞乱LINQPad,我实际上已完成投影并按照我的意愿工作,但我无法工作的是取消组中的所有ChangeListItem
除外第一个。这是我的代码:
更改类
public class Change : {
public DateTime ChangedDateTime { get; set; }
#region Navigation Properties
public virtual ICollection<ChangeDetail> Details { get; private set; }
#endregion
public Change() {
this.Details = new List<ChangeDetail>();
}
}
ChangeDetail 类
public class ChangeDetail {
public string Details { get; set; }
#region Navigation Properties
public int ChangeId { get; set; }
public virtual Change Change { get; set; }
#endregion
}
我的LINQPad尝试
var changes =
Changes
.SelectMany(c => c.Details)
.OrderByDescending(c => c.Change.ChangedDateTime)
.Select(c => new ChangeListItem
{
ChangedDateTime = c.Change.ChangedDateTime,
Details = c.Details
})
.GroupBy(c => c.ChangedDateTime)
.ForEach(g =>
{
g
.Skip(1)
.ForEach(c =>
{
c.ChangedDateTime = null;
});
});
当我将其转储到结果窗格中时,我仍然会收到ChangeListItem
组的集合,但ChangedDateTime
属性仍然填写完整。我确定我错过了一路上的重新分配,即使我认为我所做的那个应该足够好。我怎样才能得到我想要的东西?
我想离开这个:
对此:
更新根据此处的要求,ForEach
扩展程序的代码为:
public static class IQueryableExtensions {
public static IQueryable<T> ForEach<T>(
this IEnumerable<T> source,
Action<T> action) {
if (source == null) {
throw new ArgumentNullException("source");
}
if (action == null) {
throw new ArgumentNullException("action");
}
foreach (T t in source) {
action(t);
}
return source.AsQueryable<T>();
}
}
答案 0 :(得分:5)
您正在处理LINQ 查询,就像它是集合一样。我假设您的ForEach
扩展名如下:
foreach(var item in source)
{
SideEffect(item);
}
return source;
此处查询查询结果一次,并且每个结果项都会发生变异。但是当你再次枚举查询时,其结果是从头开始重新创建;因此,突变就会丢失。
理论上,可以在代码中包含一些策略性ToList()
调用以获得所需的效果。但这并非符合LINQ的精神。不要混合LINQ和副作用。如果你想有条件地投射一些物品而不让其他物品保持不变,那么就这样做:
changeGroup.Select( (c, index) => index == 0 ? c : new ChangeListItem
{
ChangedDateTime = null,
Details = c.Details
} );
顺便说一下,在执行此转换之前,您可能需要调用AsEnumerable()
,因为我不认为LINQ to Entities支持包含项目索引的Select
的重载(可以&#39;尽管如此,我还记得了。