我在尝试使用ForEach()
和linq计算模型上的3个字段时遇到问题。查询返回"活动"对于特定问题。其中一个字段是" TimeSpent",它是long
。它基本上是花在该项目上的时间(以毫秒为单位)。我试图根据这个" TimeSpent"来显示日,小时和分钟。字段,用于每个活动。这是模特:
public class ActivityGridModel
{
public DateTime ActivityDate { get; set; }
public string ActivityType { get; set; }
public string Notes { get; set; }
public string EnteredBy { get; set; }
public long TimeSpent { get; set; }
public int Days { get; set; }
public int Hours { get; set; }
public int Minutes { get; set; }
}
这是我构建的查询:
var activities = from a in Session.Context.Activities
join at in Session.Context.ActivityTypes
on a.ActivityTypeID equals at.ActivityTypeID
join u in Session.Context.Users
on a.CreatedByUserID equals u.UserID
where a.IssueID == issueId
select new ActivityGridModel()
{
ActivityDate = a.ActivityDate,
ActivityType = at.ActivityType1,
Notes = a.Notes,
EnteredBy = u.FirstName + " " + u.LastName,
TimeSpent = a.TimeSpent
};
在这里,我尝试填充模型的天,小时和分钟:
activities.ToList().ForEach(a =>
{
TimeSpan timeSpent = new TimeSpan(a.TimeSpent);
a.Days = timeSpent.Days;
a.Hours = timeSpent.Hours;
a.Minutes = timeSpent.Minutes;
});
return activities.ToList();
我得到了结果中的所有其他字段,但是天,小时和分钟都是0.我不太确定我做错了什么。任何帮助表示赞赏。
答案 0 :(得分:2)
首先将列表存储到变量中,然后使用Foreach
var activityList = activities.ToList();
activityList.ForEach(a =>
{
TimeSpan timeSpent = new TimeSpan(a.TimeSpent);
a.Days = timeSpent.Days;
a.Hours = timeSpent.Hours;
a.Minutes = timeSpent.Minutes;
});
return activityList;
您首先在创建的列表上使用.ToList()
执行查询(使用ForEach
),但随后您将丢弃该列表。
然后,您再次执行相同的查询并将结果作为列表返回,而不进行任何修改,这使得ForEach
毫无意义。
Linq查询被懒惰地评估。因此,每次执行查询时都会得到一个新列表。
这里重要的是ForEach
没有返回列表,它会更改它。因此,您必须将列表放入变量中,进行更改然后返回修改后的列表。
答案 1 :(得分:1)
@ Selman22有解决方案,但这就是代码无效的原因。
对活动的原始分配显示为IQueryable<ActivityGridModel>
,因此对其执行.ToList()
两次有效地创建了两组数据。第一个列表更新,然后像@ Selman22说它被扔掉了。第二个列表是一组未更新的新数据。
除了冗余创建之外,它看起来会在上下文中执行两次枚举,这可能也很昂贵。请记住,您应该减少对方法的调用次数,这可能很昂贵。它可能看起来没有很多执行,但可能有一个抽象层从磁盘,数据库或Web服务读取/写入数据。
以下是@ Selman22对该解决方案所说的重复:
var activityList = activities.ToList();
activityList.ForEach(a =>
{
TimeSpan timeSpent = new TimeSpan(a.TimeSpent);
a.Days = timeSpent.Days;
a.Hours = timeSpent.Hours;
a.Minutes = timeSpent.Minutes;
});
return activityList;
答案 2 :(得分:1)
这在任何意义上都是错误的。天,小时和分钟必须是只读属性,在内部从TimeSpent计算它们的值。您实施此方法的方式最终会导致您的对象无效数据。对于exapmle:
var model = new ActivityGridModel { TimeSpent = X };
model.Days = 5;
model.Hours = 10;
这有效吗?
更好的方法是在内部计算天数,小时数和分钟数:
public class ActivityGridModel
{
public DateTime ActivityDate { get; set; }
public string ActivityType { get; set; }
public string Notes { get; set; }
public string EnteredBy { get; set; }
private long _timeSpent;
public long TimeSpent
{
get
{
return _timeSpent;
}
set
{
_timeSpent = value;
var tsSpent = new TimeSpan(_timeSpent);
Days = tsSpent .Days;
Hours = tsSpent .Hours;
Minutes = tsSpent .Minutes;
}
}
public int Days { get; private set; //readonly for class clients }
public int Hours { get; private set; //readonly for class clients}
public int Minutes { get; private set; //readonly for class clients}
}
答案 3 :(得分:0)
var activities = from a in Session.Context.Activities
join at in Session.Context.ActivityTypes
on a.ActivityTypeID equals at.ActivityTypeID
join u in Session.Context.Users
on a.CreatedByUserID equals u.UserID
where a.IssueID == issueId
select new ActivityGridModel()
{
ActivityDate = a.ActivityDate,
ActivityType = at.ActivityType1,
Notes = a.Notes,
EnteredBy = u.FirstName + " " + u.LastName,
TimeSpent = a.TimeSpent,
Days = a.TimeSpent.Days,
Hours = a.TimeSpent.Hours,
Minutes = a.TimeSpent.Minutes
};