我有一个对象列表,我想更新其中一个对象中的特定成员变量。我知道LINQ是专为查询而设计的,并不意味着更新不可变数据列表。实现这一目标的最佳方法是什么?如果效率不高,我不需要使用LINQ作为解决方案。
创建Update扩展方法是否有效?如果是这样,我该怎么做呢?
EXAMPLE:
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).Update(
trade => trade.Buy += optionQty);
答案 0 :(得分:30)
尽管linq并不是要更新不可变数据的列表,但是获取要更新的项目非常方便。我想你会这样:
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).ToList().ForEach( trade => trade.Buy += optionQty);
答案 1 :(得分: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);
}
}
答案 2 :(得分:1)
所以你希望在这里得到一个结果。在这种情况下,您可以考虑使用SingleOrDefault
方法:
var record =
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).SingleOrDefault();
if (record != null)
record.Buy += optionQty;
请注意,SingleOrDefault
方法需要返回完全一个或零的值(非常类似于表中某些唯一主键的行)。如果返回多个记录,该方法将抛出异常。
答案 3 :(得分:0)
要创建这样的方法,您可以从它的原型开始:
public static class UpdateEx {
public void Update(this IEnumerable<T> items,
Expression<Action> updateAction) {
}
}
这很容易。
困难的部分是编译 Expression<Action>
到SQL更新语句。根据您希望支持的语法数量,这样的编译器的复杂程度可以从微不足道到不可能。
有关编译Linq表达式的示例,请参阅sqlite-net project的TableQuery
类。