2014-09-10 129 views
2

我無法使用ForEach()和linq來計算我的模型中的3個字段。查詢返回特定問題的「活動」。其中一個領域是「TimeSpent」,這是一個long。基本上是以毫秒爲單位花費在這個項目上的時間。我試圖根據每個活動的「TimeSpent」字段顯示Days,Hours和Minutes。這裏的型號:Linq ForEach()不填充字段

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

我得到了結果中的所有其他字段,但Days,Hours和Minutes都是0.我不太確定我做錯了什麼。任何幫助表示讚賞。

回答

1

這是錯誤在任何意義。天數,小時數和分鐘數必須是隻讀的屬性,可以從TimeSpent內部計算它們的值。你已經實現了這個方法,你可以在你的objet中得到無效的數據。對於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} 
} 
+0

雖然@ Selman22答案的作品是正確的,我決定使用這個解決方案,因爲brz是正確的,這些領域應該內部計算。 – Robert 2014-09-11 14:11:12

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

這將是值得向大家解釋*這是必需的原因。 – 2014-09-10 16:59:50

+0

@JonSkeet足夠清楚了嗎? – 2014-09-10 17:12:32

+0

是的,那絕對會更好。 – 2014-09-10 17:15:07

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 
       }; 
+0

這與OP的代碼沒有做同樣的事,你不能像OP的代碼那樣做,因爲DB不能把它轉換成SQL。 – Servy 2014-09-10 17:17:51

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;