从 DataReader 列中查找最长的字符串
Find longest string from DataReader column
是否可以创建一个 Linq 来检索 DataReader 列的最长字符串值?列数据应转换为字符串,然后 return 最长的字符串。
到目前为止我所知道的是如何使用可枚举的 DataTable 获得相同的东西(如我所问 ),示例:
string maxString = dt
.AsEnumerable()
.Select(row => row[mycolumn].ToString())
.OrderByDescending(st => st.Length)
.FirstOrDefault();
我试过像这样组合 DataReader 的上层解决方案:
var enumerable = reader
.Cast<IDataRecord>();
string max_string = enumerable
.Select(record => record.GetName(col).ToString())
.Aggregate((s, a) => a.Length > s.Length ? a : s);
不幸的是这不起作用,我得到
Sequence contains no elements in at
System.Linq.Enumerable.Aggregate
错误。提前感谢您的帮助:)
编辑:我正在寻找一种解决方案,无需直接从 DataReader 对象将数据加载到 Datatable 等中。我试图避免 "Out of memory exception",因为数据很大。
Power Mouse 建议的最新尝试(它 return 的正确值,但仅来自第 1 列):
for (int col = 0; col < reader.FieldCount; col++)
{
string col_name = reader.GetName(col).ToString();
var enumerable = reader.Cast<IDataRecord>();
string max_string = enumerable.Where(x => enumerable.Max(y => y[col_name].ToString()
.Length) == x[col_name].ToString().Length)
.FirstOrDefault()?[col_name].ToString();
Console.WriteLine("max string of column is : " + max_string);
}
所以根据您最初的要求:当您在运行中使用 DataReader 时,您需要在特定列中找到最长的文本。
请查看示例
string storedString = String.Empty;
SqlConnection connection = new SqlConnection(this.Connection.ConnectionString);
using (connection)
{
string SQLcommand = "select * FROM (VALUES(1, 'xxx' ), (2, 'really long string xxxxxx'), (3, 'short string'), (4, 'another string')) t (id, fName)";
SqlCommand command = new SqlCommand(SQLcommand, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
storedString = reader.Cast<IDataRecord>()
.Where(w=> w.GetOrdinal("fName").ToString().Length == reader.Cast<IDataRecord>()
.Max(m => m.GetOrdinal("fName")
.ToString().Length))
.Select(s=> s.GetString(1))
.FirstOrDefault();
}
}
Console.WriteLine($"The longest string: {storedString}. charcount= {storedString.Length}");
结果将是:
最长字符串:真长字符串xxxxxx。字符数= 25
正如您解释的那样,您需要检查多个列:
string storedNameString = String.Empty;
string storedName2String = String.Empty;
SqlConnection connection = new SqlConnection(this.Connection.ConnectionString);
using (connection)
{
string SQLcommand = "select * FROM (VALUES(1, 'xxx', 'dddddd' ), (2, 'really long string xxxxxx','dfghdt'), (3, 'short string', 'anothercolumn long string'), (4, 'another string', 'test')) t (id, fName, fName2)";
SqlCommand command = new SqlCommand(SQLcommand, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string fName = reader.GetString(reader.GetOrdinal("fName")).ToString();
if(fName.Length >= storedNameString.Length)
storedNameString = fName;
string fName2 = reader.GetString(reader.GetOrdinal("fName2")).ToString();
if (fName2.Length >= storedName2String.Length)
storedName2String = fName2;
}
}
Console.WriteLine($"The longest string: {storedNameString}. charcount= {storedNameString.Length}");
Console.WriteLine($"The longest string: {storedName2String}. charcount= {storedName2String.Length}");
我解决了我的问题,不幸的是没有 LINQ。问题是,对于 DataReader,您不能像 DataTable 一旦存储在内存中那样简单地遍历行和列,但是您必须在 reader.Read() 时执行某种相同的逻辑方法是 运行。
所以,我能想到的最好的办法是将列索引及其字符串值存储到字典中,而 .Read() 方法是 运行.
这样做时,您必须注意字符串空格和空值。这是我的解决方案,对我来说运行良好:
Dictionary<int, string> col_values = new Dictionary<int, string>();
using (OracleDataReader reader = cmd.ExecuteReader())
{
for (int i = 0; i < reader.FieldCount; i++)
{
//First add indexes to Dictionary
// I add column names here - didn't test for string.Empty !!
col_values.Add(i, string.Empty);
}
//Then read row by row and modify Dictionary - If text is larger than string.Empty
//Dictionary must be .ToArray(), or else you'll have an error for modifying collection
while (reader.Read())
{
foreach (var item in col_values.ToArray())
{
string rdr_text = reader[item.Key].ToString().Trim()??string.Empty;
if (item.Value.Length<rdr_text.Length)
{
col_values[item.Key] = rdr_text;
}
}
}
foreach (var item in col_values)
{
//...And here we have all longest strings stored, for each column...Job done
}
}
对于我的目的,此迭代在 4 分钟内读取了大约 2.3 mio 行和 12 列。它并不快,但至少它有效。如果有人有better/faster想法请提供答案。
是否可以创建一个 Linq 来检索 DataReader 列的最长字符串值?列数据应转换为字符串,然后 return 最长的字符串。
到目前为止我所知道的是如何使用可枚举的 DataTable 获得相同的东西(如我所问
string maxString = dt
.AsEnumerable()
.Select(row => row[mycolumn].ToString())
.OrderByDescending(st => st.Length)
.FirstOrDefault();
我试过像这样组合 DataReader 的上层解决方案:
var enumerable = reader
.Cast<IDataRecord>();
string max_string = enumerable
.Select(record => record.GetName(col).ToString())
.Aggregate((s, a) => a.Length > s.Length ? a : s);
不幸的是这不起作用,我得到
Sequence contains no elements in at System.Linq.Enumerable.Aggregate
错误。提前感谢您的帮助:)
编辑:我正在寻找一种解决方案,无需直接从 DataReader 对象将数据加载到 Datatable 等中。我试图避免 "Out of memory exception",因为数据很大。
Power Mouse 建议的最新尝试(它 return 的正确值,但仅来自第 1 列):
for (int col = 0; col < reader.FieldCount; col++)
{
string col_name = reader.GetName(col).ToString();
var enumerable = reader.Cast<IDataRecord>();
string max_string = enumerable.Where(x => enumerable.Max(y => y[col_name].ToString()
.Length) == x[col_name].ToString().Length)
.FirstOrDefault()?[col_name].ToString();
Console.WriteLine("max string of column is : " + max_string);
}
所以根据您最初的要求:当您在运行中使用 DataReader 时,您需要在特定列中找到最长的文本。 请查看示例
string storedString = String.Empty;
SqlConnection connection = new SqlConnection(this.Connection.ConnectionString);
using (connection)
{
string SQLcommand = "select * FROM (VALUES(1, 'xxx' ), (2, 'really long string xxxxxx'), (3, 'short string'), (4, 'another string')) t (id, fName)";
SqlCommand command = new SqlCommand(SQLcommand, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
storedString = reader.Cast<IDataRecord>()
.Where(w=> w.GetOrdinal("fName").ToString().Length == reader.Cast<IDataRecord>()
.Max(m => m.GetOrdinal("fName")
.ToString().Length))
.Select(s=> s.GetString(1))
.FirstOrDefault();
}
}
Console.WriteLine($"The longest string: {storedString}. charcount= {storedString.Length}");
结果将是: 最长字符串:真长字符串xxxxxx。字符数= 25
正如您解释的那样,您需要检查多个列:
string storedNameString = String.Empty;
string storedName2String = String.Empty;
SqlConnection connection = new SqlConnection(this.Connection.ConnectionString);
using (connection)
{
string SQLcommand = "select * FROM (VALUES(1, 'xxx', 'dddddd' ), (2, 'really long string xxxxxx','dfghdt'), (3, 'short string', 'anothercolumn long string'), (4, 'another string', 'test')) t (id, fName, fName2)";
SqlCommand command = new SqlCommand(SQLcommand, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string fName = reader.GetString(reader.GetOrdinal("fName")).ToString();
if(fName.Length >= storedNameString.Length)
storedNameString = fName;
string fName2 = reader.GetString(reader.GetOrdinal("fName2")).ToString();
if (fName2.Length >= storedName2String.Length)
storedName2String = fName2;
}
}
Console.WriteLine($"The longest string: {storedNameString}. charcount= {storedNameString.Length}");
Console.WriteLine($"The longest string: {storedName2String}. charcount= {storedName2String.Length}");
我解决了我的问题,不幸的是没有 LINQ。问题是,对于 DataReader,您不能像 DataTable 一旦存储在内存中那样简单地遍历行和列,但是您必须在 reader.Read() 时执行某种相同的逻辑方法是 运行。
所以,我能想到的最好的办法是将列索引及其字符串值存储到字典中,而 .Read() 方法是 运行.
这样做时,您必须注意字符串空格和空值。这是我的解决方案,对我来说运行良好:
Dictionary<int, string> col_values = new Dictionary<int, string>();
using (OracleDataReader reader = cmd.ExecuteReader())
{
for (int i = 0; i < reader.FieldCount; i++)
{
//First add indexes to Dictionary
// I add column names here - didn't test for string.Empty !!
col_values.Add(i, string.Empty);
}
//Then read row by row and modify Dictionary - If text is larger than string.Empty
//Dictionary must be .ToArray(), or else you'll have an error for modifying collection
while (reader.Read())
{
foreach (var item in col_values.ToArray())
{
string rdr_text = reader[item.Key].ToString().Trim()??string.Empty;
if (item.Value.Length<rdr_text.Length)
{
col_values[item.Key] = rdr_text;
}
}
}
foreach (var item in col_values)
{
//...And here we have all longest strings stored, for each column...Job done
}
}
对于我的目的,此迭代在 4 分钟内读取了大约 2.3 mio 行和 12 列。它并不快,但至少它有效。如果有人有better/faster想法请提供答案。