我有两个不同的集合:
List<int>
IEnumerable<IDataRecord>
第一个包含主键列表。第二个包含数据记录。我想要做的是根据给定的列名确定第一个集合中哪些主键不存在,并将它们作为新集合返回。
例如,如果我有这个:
private List<int> _currentKeys = new List<int>();
public void Update(DbDataReader reader, string keyColumn) {
var records = reader.AsEnumerable(); // my own extension method
var difference = // LINQ stuff here
}
Say _currentKeys
包含[1,2,3,4,5],reader
包含名为ID的列中值为[1,4,5]的记录。如果我调用Update,我需要获得一个包含[2,3]的集合。
与往常一样,我觉得这很简单,但两个系列不同类型的事实完全让我失望。结合我还没有使用过LINQ的事实。
答案 0 :(得分:3)
诀窍是在主键列表中查询您的阅读器不包含的键。 where语句指定要比较的阅读器中的哪一列。但是,它们必须具有相同的数据类型。
List<int> _currentKeys = new List() { 1, 2, 3, 4, 5);
List<int> NotFound = (
from pk in _currentKeys
where !reader.Select(rec => rec.MyFieldToCompare).Contains(pk)
select pk).ToList();
如果它们的数据类型不同,只需转换内存集合以匹配数据库集合的类型。 IE如果您的主键在数据库中保存为varchar,您可以像这样隐藏_currentKeys:
List<string> _currentKeysStr =
Array.ConvertAll<int, string>
(_currentKeys.ToArray(), Convert.ToString).ToList();
答案 1 :(得分:0)
你可以这样做:
var difference = _currentKeys.Where(k => !records.Any(r => (int)r[keyColumn] == k));
我假设keyColumn标识的列可以强制转换为int。
答案 2 :(得分:0)
我过去采用的方法是:
IEnumerable<int> exceptions = _currentKeys.ToArray().Except(reader.Select(x => x.ID).ToArray());
你有一点投射,我不是百分百肯定是必要的,但我没有看到我的需求的重大表现。
答案 3 :(得分:0)
将Records集合的值投影到Int列表中并使用except函数(返回一个集合中不在另一个集合中的值)
var difference = _currentKeys.Except(records.Select(r=>r.ID)