使用 IDataReader 正确读取值
Using IDataReader to read the values correctly
我使用数据reader 使用 sqlcommand 从 sqltable 中检索一些值。现在,当我第一次执行 reader 以 select 值并将它们分配给 RemovedRows 变量时,它工作得很好。但是当它下次执行填充 AddedRows 变量时,它 returns 什么都没有。现在,如果我交换变量位置,AddedRows 将有值,而后者将没有任何值。所以基本上 reader 执行一次,下一次它不会执行,也不会给出任何错误,如 reader 已关闭等。
using (IDataReader reader = _changeTable.ExecuteReader())
{
RemovedRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] })
.Where(r => r.Operation.Equals("D")).Select(r => (long)r.LogID).ToList();
AddedRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] })
.Where(r => r.Operation.Equals("I")).Select(r => (long)r.LogID).ToList();
}
public static IEnumerable<T> Select<T>(this IDataReader reader,
Func<IDataReader, T> projection)
{
while (reader.Read())
{
yield return projection(reader);
}
}
一个解决方案是在 new List<T>
中使用 reader 的值并访问新列表值而不用担心 reader 状态。我能够创建一个列表,但由于属性是匿名类型,我无法访问它。
我创建了 new List<T>
并像这样使用它:
public static List<T> CreateList<T>(params T[] elements)
{
return new List<T>(elements);
}
var values = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }).ToList();
var newList = Helper.CreateList(values);
RemovedRows = newList.Where(r => r.Operation.Equals("D")).Select(r => (long)r.LogID).ToList();
此处不允许我访问匿名类型的 Operation 和 LogID 属性。
所以我的问题是如何执行 reader(下面的代码)并在关闭 reader 后使用它的值:
var values = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }).ToList();
reader 已经被枚举,并且只允许一次只进访问,因此尝试再次枚举它以获得 AddedRows
结果是一个空集合。我建议将所有相关行读入内存,然后过滤成单独的查询:
string[] ops = {"D","I"};
IEnumerable<long> removedRows;
IEnumerable<long> addedRows;
using (IDataReader reader = _changeTable.ExecuteReader())
{
var allRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] })
.Where(r => ops.Contains(r.Operation)
.ToList();
removedRows = allRows.Where(r => r.Operation.Equals("D"))
.Select(r => (long)r.LogID);
addedRows = allRows.Where(r => r.Operation.Equals("I"))
.Select(r => (long)r.LogID);
}
您也可以使用 GroupBy
或 ToLookup
来获得类似的结果,但除非您有严重的性能问题,否则请使用对您最有意义的任何内容。
我使用数据reader 使用 sqlcommand 从 sqltable 中检索一些值。现在,当我第一次执行 reader 以 select 值并将它们分配给 RemovedRows 变量时,它工作得很好。但是当它下次执行填充 AddedRows 变量时,它 returns 什么都没有。现在,如果我交换变量位置,AddedRows 将有值,而后者将没有任何值。所以基本上 reader 执行一次,下一次它不会执行,也不会给出任何错误,如 reader 已关闭等。
using (IDataReader reader = _changeTable.ExecuteReader())
{
RemovedRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] })
.Where(r => r.Operation.Equals("D")).Select(r => (long)r.LogID).ToList();
AddedRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] })
.Where(r => r.Operation.Equals("I")).Select(r => (long)r.LogID).ToList();
}
public static IEnumerable<T> Select<T>(this IDataReader reader,
Func<IDataReader, T> projection)
{
while (reader.Read())
{
yield return projection(reader);
}
}
一个解决方案是在 new List<T>
中使用 reader 的值并访问新列表值而不用担心 reader 状态。我能够创建一个列表,但由于属性是匿名类型,我无法访问它。
我创建了 new List<T>
并像这样使用它:
public static List<T> CreateList<T>(params T[] elements)
{
return new List<T>(elements);
}
var values = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }).ToList();
var newList = Helper.CreateList(values);
RemovedRows = newList.Where(r => r.Operation.Equals("D")).Select(r => (long)r.LogID).ToList();
此处不允许我访问匿名类型的 Operation 和 LogID 属性。
所以我的问题是如何执行 reader(下面的代码)并在关闭 reader 后使用它的值:
var values = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }).ToList();
reader 已经被枚举,并且只允许一次只进访问,因此尝试再次枚举它以获得 AddedRows
结果是一个空集合。我建议将所有相关行读入内存,然后过滤成单独的查询:
string[] ops = {"D","I"};
IEnumerable<long> removedRows;
IEnumerable<long> addedRows;
using (IDataReader reader = _changeTable.ExecuteReader())
{
var allRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] })
.Where(r => ops.Contains(r.Operation)
.ToList();
removedRows = allRows.Where(r => r.Operation.Equals("D"))
.Select(r => (long)r.LogID);
addedRows = allRows.Where(r => r.Operation.Equals("I"))
.Select(r => (long)r.LogID);
}
您也可以使用 GroupBy
或 ToLookup
来获得类似的结果,但除非您有严重的性能问题,否则请使用对您最有意义的任何内容。