2010-03-15 64 views
12

我有一個對象列表,我想更新其中一個對象中的特定成員變量。我知道LINQ是爲查詢而設計的,並不意味着更新不可變數據的列表。什麼是實現這一目標的最佳方式?如果解決方案效率不高,我不需要使用LINQ。如何用列表使用LINQ和C更新元素#

會創建更新擴展方法嗎?如果是的話,我會怎麼做呢?

EXAMPLE: 
(from trade in CrudeBalancedList 
where trade.Date.Month == monthIndex 
select trade).Update(
trade => trade.Buy += optionQty); 
+0

我看到這個條目,並認爲鏈接到這將是適用於任何希望我的問題。 http://stackoverflow.com/questions/1344140/extension-method-for-up-date-in-linq-to-objects – Addie 2010-03-16 00:45:56

回答

29

雖然LINQ並不意味着一成不變的更新數據列表,它是獲取要更新的項目非常方便。我認爲對你來說這將是:

(from trade in CrudeBalancedList 
    where trade.Date.Month == monthIndex 
    select trade).ToList().ForEach(trade => trade.Buy += optionQty); 
+1

這將生成一個新的更新列表或它將更新CrudeBalancedList? – 2013-09-19 05:13:10

+2

在ToList()方法被調用的地方,有一個滿足條件的交易對象列表。這個列表沒有變量,所以只要執行這一行就會成爲垃圾收集的目標。如果你想利用這個列表不僅僅是做[trade.Buy + = optionQty],那麼你會想將這行代碼分離出來。首先定義並設置一個變量,如下所示:列表 monthlyCrudeBalancedList =(從交易等等然後下一行:monthlyCrudeBalancedList.ForEach(交易=>等等)然後,你會有一個新的列表引用 – 2013-12-10 21:54:10

1

所以你期望在這裏得到一個單一的結果。在這種情況下,你可能會考慮利用SingleOrDefault方法:

var record = 
    (from trade in CrudeBalancedList 
    where trade.Date.Month == monthIndex 
    select trade).SingleOrDefault(); 

if (record != null) 
    record.Buy += optionQty; 

注意,SingleOrDefault方法希望那裏是只有一個或零返回值(很像一些獨特的主鍵在一個表中的行)。如果返回多個記錄,則該方法將引發異常。

+0

或使用類似FirstOrDefault方法。如果返回多條記錄,它不會拋出異常。 – WEFX 2013-05-09 15:33:01

0

要創建這樣一個方法,你將與它的原型開始:

public static class UpdateEx { 
    public void Update(this IEnumerable<T> items, 
         Expression<Action> updateAction) { 
    } 
} 

這是比較容易的部分。

困難的部分將編譯Expression<Action>到一個SQL更新語句。根據你想要支持多少語法,這種編譯器的複雜性可能從簡單到不可能。

有關編譯Linq表達式的示例,請參見sqlite-net projectTableQuery類。

4

我不確定這是否是最好的方法,但可以讓您更新列表中的元素。

測試對象:

public class SomeClass { 
     public int Value { get; set; } 
     public DateTime Date { get; set; } 
    } 

擴展方法:

public static class Extension { 
     public static void Update<T>(this T item, Action<T> updateAction) { 
      updateAction(item); 
     } 
    } 

測試:

public void Test() 
{ 
    // test data 
    List<SomeClass> list = new List<SomeClass>() 
    { 
     new SomeClass {Value = 1, Date = DateTime.Now.AddDays(-1)}, 
     new SomeClass {Value = 2, Date = DateTime.Now }, 
     new SomeClass {Value = 3, Date = DateTime.Now.AddDays(1)} 
    }; 
    // query and update 
    (from i in list where i.Date.Day.Equals(DateTime.Now.Day) select i).First().Update(v => v.Value += 5); 

    foreach (SomeClass s in list) { 
     Console.WriteLine(s.Value); 
    } 
} 
+0

或者你可以這樣做:'(from i in list where i.Date.Day.Equals(DateTime.Now.Day)select i).First()。Value + = 4;' – HellBaby 2015-03-02 12:49:57