我有一个 Item 类,它表示列表中的一个项目。我在其中调用返回数据表的存储过程的函数,我需要将数据表转换为项目数组。 这是我所做的:
public class Item
{
private string _ItemIdDataName = "item_id";
private string _ItemNameDataName = "item_name";
private string _PriceDataName = "price";
public long ItemId { get; set; }
public string ItemName { get; set; }
public float Price { get; set; }
private Item(DataRow row)
{
if (row != null)
{
ItemId = long.Parse(row[_ItemIdDataName].ToString());
ItemName = row[_ItemNameDataName].ToString();
Price = float.Parse(row[_PriceDataName].ToString());
}
}
public Item[] load()
{
DataTable dt=DBHandler.GetItems();//Stored procedure that returns DataTable
Item[] items = new Item[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
items[i] = new Item(dt.Rows[i]);
}
return items;
}
}
我做的对吗? 我该如何改进?
最佳答案
如果您只打算使用它一次,那可能没问题,但如果您要经常使用它,则应该尝试做一些更通用的东西。我写了一篇关于如何为创建对象列表的 DataTable
编写扩展方法的博文。它按照惯例工作,即对象中的属性应与存储过程中的列具有相同的名称(如果可以的话,我会更改存储过程中的名称):
public static class DataTableExtensions
{
public static IList<T> ToList<T>(this DataTable table) where T : new()
{
IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
IList<T> result = new List<T>();
foreach (var row in table.Rows)
{
var item = CreateItemFromRow<T>((DataRow)row, properties);
result.Add(item);
}
return result;
}
public static IList<T> ToList<T>(this DataTable table, Dictionary<string, string> mappings) where T : new()
{
IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
IList<T> result = new List<T>();
foreach (var row in table.Rows)
{
var item = CreateItemFromRow<T>((DataRow)row, properties, mappings);
result.Add(item);
}
return result;
}
private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
{
T item = new T();
foreach (var property in properties)
{
property.SetValue(item, row[property.Name], null);
}
return item;
}
private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties, Dictionary<string, string> mappings) where T : new()
{
T item = new T();
foreach (var property in properties)
{
if(mappings.ContainsKey(property.Name))
property.SetValue(item, row[mappings[property.Name]], null);
}
return item;
}
}
现在你可以调用
var items = dt.ToList<Item>();
或
var mappings = new Dictionary<string,string>();
mappings.Add("ItemId", "item_id");
mappings.Add("ItemName ", "item_name");
mappings.Add("Price ", "price);
var items = dt.ToList<Item>(mappings);
博文在这里:http://blog.tomasjansson.com/2010/11/convert-datatable-to-generic-list-extension
有很多方法可以扩展它,您可以包含某种映射字典,告诉扩展如何映射列,这样名称就不需要匹配了。或者,您可以添加要在映射中排除的属性名称列表。
更新:您正在创建的对象 (Item
) 必须具有默认构造函数,否则私有(private)方法将无法创建它。由于解决方案的工作方式是首先创建对象,而不是使用从反射中获得的属性来设置对象的值。
更新 2: 我添加了带有映射字典的部分,但我自己没有尝试过,所以它可能无法编译。但是,这个概念就在那里,我认为它可行。
关于c# - 获取数据行到 C# 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4593663/