从数据表获取单个值的最佳方法?
我有许多包含这样的表的静态类:
using System;
using System.Data;
using System.Globalization;
public static class TableFoo
{
private static readonly DataTable ItemTable;
static TableFoo()
{
ItemTable = new DataTable("TableFoo") { Locale = CultureInfo.InvariantCulture };
ItemTable.Columns.Add("Id", typeof(int));
ItemTable.Columns["Id"].Unique = true;
ItemTable.Columns.Add("Description", typeof(string));
ItemTable.Columns.Add("Data1", typeof(int));
ItemTable.Columns.Add("Data2", typeof(double));
ItemTable.Rows.Add(0, "Item 1", 1, 1.0);
ItemTable.Rows.Add(1, "Item 2", 1, 1.0);
ItemTable.Rows.Add(2, "Item 3", 2, 0.75);
ItemTable.Rows.Add(3, "Item 4", 4, 0.25);
ItemTable.Rows.Add(4, "Item 5", 1, 1.0);
}
public static DataTable GetItemTable()
{
return ItemTable;
}
public static int Data1(int id)
{
DataRow[] dr = ItemTable.Select("Id = " + id);
if (dr.Length == 0)
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
return (int)dr[0]["Data1"];
}
public static double Data2(int id)
{
DataRow[] dr = ItemTable.Select("Id = " + id);
if (dr.Length == 0)
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
return (double)dr[0]["Data2"];
}
}
是否有更好的方法来编写 Data1 或 Data2 方法,从与给定 id 匹配的单行返回单个值?
更新 #1:
我创建了一个看起来相当不错的扩展方法:
public static T FirstValue<T>(this DataTable datatable, int id, string fieldName)
{
try
{
return datatable.Rows.OfType<DataRow>().Where(row => (int)row["Id"] == id).Select(row => (T)row[fieldName]).First();
}
catch
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
}
我的 Data1 方法变成:
public static int Data1(int id)
{
return ItemTable.FirstValue<int>(id, "Data1");
}
并且 Data2 变成:
public static double Data2(int id)
{
return ItemTable.FirstValue<double>(id, "Data2");
}
感谢您的所有回复,特别是 Anthony Pegram,他给出了非常好的单行LINQ&拉姆达代码。
I have a number of static classes that contain tables like this:
using System;
using System.Data;
using System.Globalization;
public static class TableFoo
{
private static readonly DataTable ItemTable;
static TableFoo()
{
ItemTable = new DataTable("TableFoo") { Locale = CultureInfo.InvariantCulture };
ItemTable.Columns.Add("Id", typeof(int));
ItemTable.Columns["Id"].Unique = true;
ItemTable.Columns.Add("Description", typeof(string));
ItemTable.Columns.Add("Data1", typeof(int));
ItemTable.Columns.Add("Data2", typeof(double));
ItemTable.Rows.Add(0, "Item 1", 1, 1.0);
ItemTable.Rows.Add(1, "Item 2", 1, 1.0);
ItemTable.Rows.Add(2, "Item 3", 2, 0.75);
ItemTable.Rows.Add(3, "Item 4", 4, 0.25);
ItemTable.Rows.Add(4, "Item 5", 1, 1.0);
}
public static DataTable GetItemTable()
{
return ItemTable;
}
public static int Data1(int id)
{
DataRow[] dr = ItemTable.Select("Id = " + id);
if (dr.Length == 0)
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
return (int)dr[0]["Data1"];
}
public static double Data2(int id)
{
DataRow[] dr = ItemTable.Select("Id = " + id);
if (dr.Length == 0)
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
return (double)dr[0]["Data2"];
}
}
Is there a better way of writing the Data1 or Data2 methods that return a single value from a single row that matches the given id?
Update #1:
I have created an extension method that seems quite nice:
public static T FirstValue<T>(this DataTable datatable, int id, string fieldName)
{
try
{
return datatable.Rows.OfType<DataRow>().Where(row => (int)row["Id"] == id).Select(row => (T)row[fieldName]).First();
}
catch
{
throw new ArgumentOutOfRangeException("id", "Out of range.");
}
}
My Data1 method then becomes:
public static int Data1(int id)
{
return ItemTable.FirstValue<int>(id, "Data1");
}
and Data2 becomes:
public static double Data2(int id)
{
return ItemTable.FirstValue<double>(id, "Data2");
}
Thanks to all your responses but especially to Anthony Pegram who gave the very nice single line of LINQ & Lambda code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否考虑过使用Linq(到数据集)?使用 Linq 表达式,您根本不需要这些 Data1 和 Data2 函数,因为查找和过滤可以在一行代码中进行。
添加示例:
这里是从臀部出发,所以请持保留态度(不要靠近 IDE:)
这是两行代码,但您可以轻松地包装 Enumerable 的获取。
Have you considered using Linq (to DataSets)? With Linq expressions you wouldn't need those Data1 and Data2 functions at all since the lookup and filtering could happen in a single line of code.
Example added:
Shooting from the hip here, so please take it with a grain of salt (not near an IDE:)
That's two lines of code but you could easily wrap the getting of the Enumerable.
我对你的架构有点怀疑,但没关系。如果您想要一个返回数据表第一行的第一个值的函数,并且您希望它是强类型的,我认为下面的函数将是一个改进。它将允许您只有一个函数,可重复用于不同类型。要使用它,您将拥有如下代码行:
如果您愿意的话:
该函数处理您通常给它的任何类型,字符串,其他值类型,可空类型,引用类型。如果该字段为空,则该函数返回该类型的“默认”值(“”表示字符串)。如果它绝对无法进行转换,因为您要求进行不可能的转换,它将抛出错误。我已将其作为数据行类型的扩展方法(称为 ValueOrDefault),并且这个傻瓜非常方便。
我根据您的情况调整了我的数据工具扩展方法。我在一家 VB 商店,我只是没有时间用 C# 重新编写整个内容,但你可以很容易地做到这一点。
I'm a little suspicious of your architecture, but never mind that. If you want a function that returns the first value of the first row of a datatable that it will get somehow, and you want it strongly typed, I think the function below will be an improvement. It would allow you to have just one function, reusable for different types. To use it you would have lines of code like:
and if you feel like it:
The function handles any type you generically give it, strings, other value types, nullable types, reference types. If the field is null, the function returns the "default" value for that type ("" for string). If it absolutely can't do the conversion, because you asked for an impossible conversion, it will throw an error. I've made it an extension method on the datarow type (called ValueOrDefault), and this sucker is really handy.
I adapted this data-tool extension method of mine for your situation. I'm in a VB shop, and I just don't have time to re-write the whole thing in C#, but you could do that easily enough.