オブジェクトのリストがあり、いずれかのオブジェクト内の特定のメンバー変数を更新したいのですが。 LINQはクエリ用に設計されており、不変データのリストを更新するためのものではないことを理解しています。これを達成するための最良の方法は何でしょうか?それが最も効率的でない場合、ソリューションにLINQを使用する必要はありません。
Update拡張メソッドの作成は機能しますか?もしそうなら、私はそれをどうやってやりますか?
EXAMPLE:
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).Update(
trade => trade.Buy += optionQty);
Linqは不変データのリストを更新するためのものではありませんが、更新するアイテムを取得するのに非常に便利です。私はあなたにとってこれは次のようになると思います:
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).ToList().ForEach( trade => trade.Buy += optionQty);
これが最善の方法かどうかはわかりませんが、リストから要素を更新できます。
テストオブジェクト:
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);
}
}
したがって、ここでは単一の結果が得られることを期待しています。その場合は、SingleOrDefault
メソッドの利用を検討してください。
var record =
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).SingleOrDefault();
if (record != null)
record.Buy += optionQty;
SingleOrDefault
メソッドは正確に1またはの値が返されることを期待していることに注意してください(一意の主キーのテーブル内の行のように)。複数のレコードが返された場合、メソッドは例外をスローします。
このようなメソッドを作成するには、そのプロトタイプから始めます。
public static class UpdateEx {
public void Update(this IEnumerable<T> items,
Expression<Action> updateAction) {
}
}
それは簡単な部分です。
難しいのは、Expression<Action>
をSQL更新ステートメントにコンパイルすることです。サポートする構文の量に応じて、このようなコンパイラーの複雑さは、取るに足らないものから不可能までさまざまです。
Linq式のコンパイル例については、 sqlite-netプロジェクト のTableQuery
クラスを参照してください。